2013-04-24 64 views
0

在運行方法內使用同步塊有意義嗎?我認爲它確實如此,只要我使用相關的鎖,而不是包含此運行方法的Runnable實例。在stackoverflow上閱讀類似問題的答案似乎證實了這一點。我試着寫一些簡單的代碼進行測試和運行方法內同步塊不從數據損壞預防:運行方法內的同步塊

public class Test { 

    public Test() { 
     ExecutorService es = Executors.newCachedThreadPool(); 
     for (int i = 0; i < 1000; i++) { 
      es.execute(new Runnable() { 
       @Override 
       public void run() { 
        synchronized (lock) { 
         sum += 1; 
        } 
       } 
      }); 
     } 
     es.shutdown(); 
     while(!es.isTerminated()) { 
     } 
    } 
    private int sum = 0; 
    private final Object lock = new Object(); 

    public static void main(String[] args) { 
     Test t = new Test(); 
     System.out.println(t.sum); 
    } 
} 

爲什麼這個代碼產生不正確的結果?這是因爲同步塊還是其他一些錯誤?我覺得我在這裏錯過了一些基本的東西。

+1

你正在做的一切正確,[它正常工作](http://ideone.com/XdaXCm)。 – dasblinkenlight 2013-04-24 01:01:31

+1

我想你可能會受到Java內存模型的影響。 – 2013-04-24 01:04:17

+0

你正在使用哪種JRE? – 2013-04-24 01:06:39

回答

1

您的執行者可能會遇到某種意外錯誤。如果發生這種情況,你不會知道它,因爲你沒有得到任何回報值來檢查。

嘗試切換到submit() instead execute()並存儲Executor爲您提供的Future實例列表。如果最後的總和小於1000,則迭代期貨並得到()每一個。如果發生異常,您會看到特定的可運行任務發生了什麼。

1

除了看起來不錯的簡單示例之外,您應該小心Runnables中的同步,以防止它們在一個Runnable等待某個資源僅由其他Runnable稍後在隊列中釋放時阻止彼此因爲當前等待的Runnable必須先完成,所以永遠不會啓動。

雖然有足夠的工作線程執行作業,但發生的可能性較小。