2010-01-28 28 views
3

我在Java中使用Collections.synchronizedCollection來保護一個我知道被許多線程同時訪問的Set。 Java的API警告:synchronizedCollection幷包含 - 我需要手動同步嗎?

「當務之急是用戶迭代它時,在返回的集合手動同步:

Collection c = Collections.synchronizedCollection(myCollection); 
    ... 
    synchronized(c) { 
     Iterator i = c.iterator(); // Must be in the synchronized block 
     while (i.hasNext()) 
     foo(i.next()); 
    } 

如果我使用c.contains(obj),是線程安全的?在內部,顯然,這是遍歷集合並查看其中的任何對象是否等於obj。我的直覺是假設這可能是同步的(如果不是這樣,這似乎是一個重大失敗),但考慮到以前的同步問題,仔細檢查似乎是明智之舉,Google的搜索答案並沒有轉變什麼都可以。

回答

7

本身,撥打contains是安全的。

問題是,人們經常測試一個集合是否包含元素,然後根據結果對集合做些什麼。

很可能,測試和操作應該被視爲單個原子操作。在這種情況下,應該獲得對集合的鎖定,並且應該在​​塊中執行這兩個操作。

+0

這是一個好點;如果它不在那裏,我並沒有考慮過如果增加價值。在這種情況下,我必須手動進行同步似乎顯然是必要的。 – DivineWolfwood 2010-01-29 00:15:35

+2

在這種情況下,爲什麼不只是添加它?底層集合實現在做什麼?例如,對於一個HashSet來說,一個包含然後一個添加就是剛剛添加的工作的兩倍。在你的情況下,無論Set實現如何,添加對於同步都是一個原子操作,無論如何你的add()代碼都需要處理重複對象(即使它本身只是檢查contains())以正確滿足加()。 – PSpeed 2010-01-29 00:22:14

+0

@主打:很好的建議。它使我不必進行同步,因爲無論如何我都會添加它。 – DivineWolfwood 2010-01-29 00:50:59

1

這是安全的,因爲contains本身是同步的。

+0

謝謝:出於好奇,你如何確認?這些同步類是通過向每種方法添加同步來完成的,這只是一種常識嗎?我試圖通過集合的.class文件,但實際上並沒有採取任何措施。 – DivineWolfwood 2010-01-29 00:09:50

+0

@DivineWolfwood爲了仔細檢查,我有JDK源代碼,所以我點擊並查看了一下。 – daveb 2010-01-29 00:15:52

+1

@DivineWolfwood:除了檢查源代碼之外,唯一可以從JavaDoc中確定的方法。這就是爲什麼記錄類的併發行爲和需求非常重要 - 這仍然是一個正在進行的工作。 – 2010-01-29 00:18:15

2

Collections.synchronizedCollection()將返回thread safe集合,這意味着 任何單個方法調用本身是thread safe。這取決於你想要做什麼。如果你想調用幾個方法,java不能使它在一起安全。

相關問題