2010-02-12 111 views
2

如果列表在doSomething()中被修改,此代碼將拋出併發修改異常。是否可以通過將代碼封裝在某個同步塊中來避免它?迭代器併發修改異常

List l = Collections.synchronizedList(new ArrayList()); 

// normal iteration -- can throw ConcurrentModificationException 
// may require external synchronization 
for (Iterator i=list.iterator(); i.hasNext();) { 
    doSomething(i.next()); 
} 
+0

「請注意,此異常不會始終指出對象已經由不同的* *線程併發修改。」所以這將是一個不。 – 2010-02-12 08:32:59

+0

何時可以引發此異常。 – 2010-02-12 09:23:04

+0

如果doSomething()在相同或不同的線程中修改'list'。 ConcurrentModificationException與線程無關。 – Robin 2010-02-12 14:49:01

回答

7
  • 如果從列表中刪除一個項目,你可以通過調用iterator.remove()而不是list.remove(iterator.next())

  • 如果添加一個項目做它有

  • 如果上面的代碼片段是同一方法的一部分,那麼您不需要同步列表或同步塊 - 其他線程無法訪問本地列表。

0

當您迭代它時,您無法對其進行修改。同步在這裏沒有幫助。

編輯:我忘了迭代器確實有remove方法。所以可以刪除。好了,創建迭代列表的副本並添加 -

3

可以修改Collection在遍歷它,如果你通過Iterator接口這樣做。您可以使用Iterator.remove()刪除元素。

+0

我想知道的是,是否可以通過將代碼放在某個同步塊中來防止ConcurrentModificationException http://www.ibm.com/developerworks/java/library/j-jtp07233.html 此鏈接提到了同步在同步塊中迭代代碼以防止併發修改異常。 – 2010-02-12 13:46:22

0

我同意其他人關於Iteratorremove()


關於同步,我想補充一點,同步設計來控制不同的線程之間的相互作用

一個對象具有多個同步方法並且會調用另一個方法是很典型的。所以語言設計師決定,同一個線程不會被同步阻止。

另外,想一想,它是一個線程被阻擋在等待自己,你有一個宏偉的飢餓的角度來看! ;-)

所以這回答了你的一個問題:通過同步你的代碼是不可能的。

0

使用CopyOnWriteArrayList而不是同步數組列表

0
List l = Collections.synchronizedList(new ArrayList()); 

synchronized(l) { 
    // normal iteration -- can throw ConcurrentModificationException 
    // may require external synchronization 
    for (Iterator i=list.iterator(); i.hasNext();) { 
     doSomething(i.next()); 
    } 
}