2013-08-01 50 views
14

返回一個列表,我發現這個在dos.oracle.com爲什麼我需要同步由Collections.synchronizedList

公共靜態列表synchronizedList(名單列表)

返回的同步(線程安全)列表支持指定的 列表。爲了保證串行訪問,通過返回列表完成對後備列表訪問的所有訪問是至關重要的。 當務之急是用戶迭代它時,返回 名單上手動同步:

List list = Collections.synchronizedList(new ArrayList()); 
     ... 
    synchronized(list) { 
     Iterator i = list.iterator(); // Must be in synchronized block 
     while (i.hasNext()) 
      foo(i.next()); 
    } 

我的問題是:爲什麼我必須同步列表進行迭代,如果Collections.synchronizedList();應該返回已經同步列表?

我只是在兩個線程訪問列表:一個線程只是添加和另一個線程獲取和刪除。你推薦哪些其他課程用於這種情況?

感謝您的閱讀。

+0

我wouldnt使用'Collections.synchronizedList()'。在自己的代碼中自己同步可能會更好 – JIV

回答

17

正在同步的列表僅意味着add,remove等操作是同步的,因此是原子的。然而,迭代不是,如果一個線程adds而另一個正在迭代,則可能會發生ConcurrentModificationException。

通過手動同步您的迭代塊,可以確保迭代時列表不會被修改。

一個替代方案是使用a CopyOnWriteArrayList,其提供an iterator,超過列表迭代,因爲它是已知的當迭代開始,而不管隨後的修飾。但是,如果您需要經常更改列表的內容,那麼該集合效率不高。

+0

謝謝!我會贊成它,但我沒有足夠的聲譽。 CopyOnWriteArrayList聽起來不錯,但是,是一個非常經常的過程,CopyOnWriteArrayList可能會有點慢。 – GabrielBB

+0

+1。你怎麼知道'add','remote'等是同步的?在javadoc中沒有任何關於它的內容。 –

+0

@LuisSep你可以得出這樣的結論:基於javadoc說列表已同步,並且迭代應該獲取列表的監視器(這與正在同步的方法一致)。看看執行情況就可以確認它。 – assylias

-1

起初我對這個話題感到困惑,因爲我發現的大多數例子都沒有上下文。我終於找到了這個博客文章,爲我清除了一些東西:http://netjs.blogspot.de/2015/09/how-and-why-to-synchronize-arraylist-in-java.html

從上面的例子看來,我只需要將我的列表與Collections.synchronizeList(),然後我可以添加和刪除項目,而無需擔心線程安全。但是在這裏需要注意的是,必須在將列表傳遞給不同的線程之前對其進行同步,因爲否則列表訪問不是互斥的。

因此,一個完整的例子是:

public class SynchroProblem implements Runnable{ 
    private List<Integer> myList; 

    //Constructor 
    public SynchroProblem(List<Integer> myList){ 
    this.myList = myList; 
    } 

    @Override 
    public void run() { 
    // Do stuff with the list .add(), .remove(), ... 
    myList.add(5); 

    // Even if mylist is synchronized the iterator is not, 
    // so for using the iterator we need the synchronized block 
    synchronized (myList){ 
     // do stuff with iterator e.g. 
     Iterator<Integer> iterator = myList.iterator(); 
     while (iterator.hasNext()){ 
     int number = iterator.next(); 
     if (number == 123){ 
      iterator.remove(); 
     } 
     } 

    } 
    } 

    public static void main(String[] args) { 

    List<Integer> originalList = new ArrayList<Integer>(); 

    // Synchronize list 
    List<Integer> syncList = Collections.synchronizedList(originalList); 

    // Create threads and pass the synchronized list 
    Thread t1 = new Thread(new SynchroProblem(syncList)); 
    Thread t2 = new Thread(new SynchroProblem(syncList)); 

    t1.start(); 
    t2.start(); 

    } 
} 
相關問題