【问题标题】:Iterator Concurrent Modifiction Exception迭代器并发修改异常
【发布时间】:2011-01-16 01:06:04
【问题描述】:

如果在 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());
}

【问题讨论】:

  • "请注意,此异常并不总是表明对象已被 不同 线程同时修改。"所以这将是一个不。
  • 什么时候可以抛出这个异常。
  • 如果 doSomething() 在同一个或不同的线程中修改了 'list'。 ConcurrentModificationException 与线程无关。

标签: java exception iterator collections synchronized


【解决方案1】:
  • 如果您要从列表中删除项目,您可以通过调用 iterator.remove() 而不是 list.remove(iterator.next()) 来完成

  • 如果您要添加项目 - 好吧,创建迭代列表的副本并将其添加到那里

  • 如果上面的代码 sn-p 是同一方法的一部分,那么您不需要同步列表或同步块 - 没有其他线程可以访问本地列表。

【讨论】:

    【解决方案2】:

    如果您通过Iterator 接口修改Collection,您可以对其进行迭代。您可以使用Iterator.remove() 删除元素。

    【讨论】:

    【解决方案3】:

    在迭代它时不能修改它。同步在这里无济于事。

    编辑:我忘记了迭代器确实有 remove 方法。所以可以去掉。

    【讨论】:

      【解决方案4】:

      我同意其他人关于Iteratorremove() 的看法。


      关于同步,我想补充一点,同步旨在控制不同线程之间的交互

      一个对象通常有几个同步的方法,一个会调用另一个。所以语言设计者决定,同一个线程在同步时不会被自己阻塞。

      还有,想一想,有一个线程被阻塞在等待自己,你有一个宏伟的饥饿视角! ;-)

      所以这回答了你的一个问题:通过同步你的代码是不可能避免这个问题的。

      【讨论】:

        【解决方案5】:

        使用CopyOnWriteArrayList 代替同步数组列表

        【讨论】:

          【解决方案6】:
          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());
             }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-09-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-08
            • 2015-09-03
            • 2018-10-21
            • 1970-01-01
            相关资源
            最近更新 更多