2013-05-09 26 views
0

我一直在使用這種模式,但我最近纔開始認爲這樣做可能不行。基本上,我使用這個模式的一些變種:Java中的不可修復「標誌」線程安全嗎?

public class SampleJavaAsync 
{ 
    public SampleJavaAsync() { } 

    private boolean completed; 
    public void start() 
    { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       //... do something on a different thread 
       completed = true; 
      } 
     }).start(); 
    } 

    public void update() 
    { 
     if (!completed) return; 
     //... do something else 
    } 
} 

*用戶有責任確保start只調用一次。無論何時何地都會調用update

我一直認爲這是Java中的線程安全,因爲即使沒有嚴格同步,我只有將completed設置爲true。一旦觀察到它是true,它將不會重置爲false。它在構造函數中被初始化爲false,這在定義中是線程安全的(除非你在其中做了一些愚蠢的事情)。那麼,以這種方式使用不可復位的標誌是否安全? (如果是的話,它甚至提供任何性能優勢?)

感謝

回答

3

Java的:它是可行的更新()無法看到更新完成的已經發生了。除非你將其標記爲volatile,否則JVM可以以優化的名義做各種事情(即按照它認爲合適的順序對讀取和寫入進行重新排序),這意味着你可以打開一個狀態,運行update()的線程永遠不會看到完成已經改變了,因爲它沒有被標記爲易失性的,並且它認爲它可以優化那些討厭的寫入(或推遲它)。

您至少會在第一次設置時出現不一致的風險,例如,對同一線程的update()調用可能會看到與來自另一個線程的同一調用不同的值。

更好地解釋:

http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html

或者,如果你真的很好奇在Java併發,買JCIP的副本:

http://jcip.net.s3-website-us-east-1.amazonaws.com/

+0

謝謝你的回答! – aboveyou00 2013-05-09 13:15:10