如何避免ConcurrentModificationException

每当我们使用java.util集合类时,我们都知道如果一个线程在另一个线程使用迭代器遍历整个集合时更改集合,那么任何对iterator.hasNext()iterator.next()调用都会抛出ConcurrentModificationException 。 即使是synchronized收集包装类SynchronizedMapSynchronizedList也只是有条件的线程安全的,这意味着所有单独的操作都是线程安全的,但是复杂操作的控制流取决于之前操作的结果,可能会受到线程问题的影响。 问题是:如何在不影响性能的情况下避免此问题。 注意:我知道CopyOnWriteArrayList


如上所述,您可以使用CopyOnWriteArrayListConcurrentHashMap等,或者您可以使用与CAS一起工作的Atomic*类。

如果你不知道Atomic*课程,他们绝对值得一看! 你可以看看这个问题。

所以要回答你的问题,你必须选择正确的工具来完成任务。 既然你不与我们分享上下文,我只能猜测。 在某些情况下,CAS会在并发收藏的其他情况下表现更好。

如果有什么不清楚的地方,你可以随时查看官方的Oracle Trails:课程:并发性


我想你提出了一个有趣的问题。
我试着考虑是否像其他人所建议的那样,ConcurrentHashMap是否可以提供帮助,但我不确定锁是基于细分的。
在这种情况下我会做什么,并且我希望我能很好地理解您的问题,即使用ReaderWriterLock锁定对您的收藏集的访问权限。
我选择这个锁的原因是因为我确实认为这需要锁定(正如你所解释的 - 迭代是由几个操作组成的),
而且,因为在阅读器线程的情况下,如果没有编写器线程在集合上工作,我不希望他们等待锁定。 感谢@Adam Arold,我注意到你提出了“同步装饰器” - 但我觉得这个装饰器对于你的需求来说“太强大了”,因为它使用了一个同步的并且不会在N个读者和M个作者的情况之间进行区分。


这是因为“标准”Java集合不是线程安全的,因为它们不同步。 使用多线程访问集合时,应该查看java.util.concurrent包。

没有这个包,在Java 5之前,必须执行手动同步:

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

或使用

Collections.synchronizedList(arrayList);

但都不能真正提供完整的线程安全功能。

有了这个包,所有进入收集原子制成,有的班级provide a snapshot of the state of the list when the iterator was constructed (见CopyOnWriteArrayListCopyOnWriteArrayList快上读的,但如果您正在执行许多写操作,这可能影响性能。

因此,如果不需要CopyOnWriteArrayList ,请查看ConcurrentLinkedQueue ,它提供a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator 。 这一点在所有方面都很有效,除非您必须比遍历整个集合更频繁地访问特定索引处的元素。

另一个选项是ConcurrentSkipListSet ,它provides expected average log(n) time cost for the contains, add, and remove operations and their variants. Insertion, removal, and access operations safely execute concurrently by multiple threads provides expected average log(n) time cost for the contains, add, and remove operations and their variants. Insertion, removal, and access operations safely execute concurrently by multiple threads并且iterators are weakly consistent

哪些并发(线程安全的)集合取决于您最擅长的操作类型。 由于它们都是Java Collection框架的一部分,因此可以将它们交换到您需要的任何地方。

链接地址: http://www.djcxy.com/p/11401.html

上一篇: How to avoid ConcurrentModificationException

下一篇: Intel C++ Compiler is extremely slow to compile recursive decltype returns