[英]Thread safety in Java class
為什么這個java類不是Thread安全的。
class TestClass {
private int x;
int get() {
return x;
}
void set(int x) {
this.x = x;
}
}
我讀到需要關鍵字synchronized
以使其線程安全嗎? 畢竟不是在原子內完成的操作?
盡管賦值本身是一個原子操作,但由於硬件和編譯器的實現不同,不同的線程可能會看到成員x的不同值。 即,由於某種緩存,一個線程的修改對於另一個線程可能是不可見的。 這通常稱為線程可見性問題 。
您可以通過在監視器上同步(使用synchronized關鍵字或java.util.concurrent鎖)或聲明x為volatile來正確同步代碼。
對於多個處理器,處理器可以緩存某些值,並且可能不反映其他線程/處理器對相同對象所做的更改。 實際上,即使使用單個處理器,也可以實現JVM以這種方式工作。
語言規范明確要求同步方法提供內存屏障,並要求重新讀取內存中的所有實例變量。
因為您的代碼未同步,所以一個線程可以設置該值,但另一個線程將返回該線程仍然緩存的值。
請閱讀Java語言規范的“內存和鎖定”一章。
由於字段“x”未聲明為volatile,因此不需要JVM確保“x”對所有其他線程可見。 也就是說,如果一個線程不斷地讀取'x'的值並且另一個線程正在寫它,那么讀取線程可能永遠不會“看到”值的變化。
不需要synchronized關鍵字,但它將起作用,因為它將創建必要的內存屏障/緩存刷新以確保'x'可見,但在這種情況下使用volatile關鍵字將更有效。
當你有兩個修改/訪問非易失性變量的方法時,它永遠不是線程安全的。 如果您只想嘗試一種方法,可以嘗試:
synchronized int getAndSet(int x, boolean set) {
if (set) this.x = x;
return this.x; // param x is for set
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.