簡體   English   中英

Java類中的線程安全性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM