2010-03-07 192 views
2

在下面的類中,我使用了一個singleThreadScheduledExecutor。我的問題是,我是否需要同時訪問dummyInt和dummyBoolean?這是否需要同步?

import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

public class Playground { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     startThread(); 

    } 

    private static void startThread() { 
     ScheduledExecutorService timer = Executors 
       .newSingleThreadScheduledExecutor(); 
     Runnable r = new Runnable() { 
      int dummyInt = 0; 
      boolean dummyBoolean = false; 

      @Override 
      public void run() { 
       dummyInt = dummyInt + 1; 

       if (dummyBoolean) { 
        dummyBoolean= false; 
       } else { 
        dummyBoolean= true; 
       } 

      } 

     }; 

     timer.scheduleAtFixedRate(r, 0, 100, TimeUnit.MILLISECONDS); 

    } 

} 

回答

3

不,你不知道。只有一個線程訪問值,所以不需要同步。

-2
dummyInt = dummyInt + 1; 

這種說法實際上是3個獨立的操作:

  1. 閱讀dummyInt
  2. 的值加1
  3. 這麼寫值回dummyInt

是的,你需要同步這一點。一個線程可能讀取該值,然後另一個線程完成所有三個操作,並且當第一個線程完成時,該值只會增加1(我希望這有意義:P)。 dummyBoolean與此類似。您在if語句中讀取它並寫入新值。

編輯

對不起,沒有正確閱讀的問題。 根據javadoc,這不應該需要同步。

+0

我知道它是3個單獨的操作。我甚至問過這個問題的原因是因爲我使用的是「singleThreadedExecutor」,因此我認爲可能不需要同步。 – systemoutprintln 2010-03-07 17:05:50

+0

不,每個線程都會得到自己的Runnable子類的實例。 – Pointy 2010-03-07 17:06:36

2

您以該機制開始的每個線程都將擁有您自己定義和實例化的「Runnable」子類的實例。因此,不可能有爭用。

-1

不,但它可能不會傷害。由於您使用的是newSingleThreadScheduledExecutor,這保證了

任務是保證執行 順序,和不超過一個 任務將是積極的,在任何給定的時間。

但是,如果你曾經改變執行者,讓Runnable跳出來讓其他人調用它,或者檢查外部值,那麼你會希望你同步它。

0

你沒有讓它​​

1

是否需要?不,只有一個線程會訪問當前實現中的變量,因此它是線程安全的。

會傷害表現嗎?嗯,是的,但不是你想象的那麼多。現代JIT編譯器非常高興地發現,在當前使用中同步是不必要的,並且幾乎消除了編譯代碼的所有開銷 - 但是仍然會有一點額外開銷檢查單線程訪問的假設是否仍然存在有效。當然,有這個JITting的開銷。

它會傷害不同步嗎?那麼,如果實現發生了變化,並且單線程訪問的假設不再成立 - 那麼開發人員就會忽略這種變化的後果。

但實際上,在這種情況下,這是否可能發生?也許不是 - 所有的代碼都包含在一個非常小的區域內......

我可能會留下一些評論文件的假設。如果我在我的項目的其他任何地方使用JCIP annotations,我甚至可能會將該類註釋爲@NotThreadSafe。關於這些註釋的使用的討論可以在Brian Goetz的Java Concurrency In Practice書中找到,註釋源代碼和jar文件可從本書的web site下載。

相關問題