How to avoid ConcurrentModificationException

Whenever we use java.util Collection classes, we have that if one thread changes a collection while another thread is traversing through it using an iterator, then any call to iterator.hasNext() or iterator.next() will throw ConcurrentModificationException . Even the synchronized collection wrapper classes SynchronizedMap and SynchronizedList are only conditionally thread-safe, which means all individual operations are thread-safe but compound operations where flow of control depends on the results of previous operations may be subject to threading issues. The question is: How to avoid this problem without affecting the performance. Note: I am aware of CopyOnWriteArrayList .


You can use CopyOnWriteArrayList or ConcurrentHashMap etc. as you mentioned above or you can use Atomic* classes which are working with CAS.

If you weren't aware of Atomic* classes they definitely worth a look! You may check out this question.

So to answer your question you have to choose the right tools for the task. Since you do not share the context with us I can just guess. In some situations CAS will perform better in others the concurrent Collections will.

If something isn't clear you can always check out the official Oracle Trails: Lesson: Concurrency


I think you raised an interesting question.
I tried thinking whether ConcurrentHashMap for example, as was suggested by others can help, but I'm not sure as the lock is segment-based.
What I would do in this case , and I do hope I understood your question well, is to lock access to your collection, using a ReaderWriterLock.
The reason I chose this lock is because I do feel this needs locking (as you explained - iteration is composed from several operations) ,
And because in case of reader threads, I do not want them to wait on lock , if no writer thread is working on the collection. Thanks to @Adam Arold I paid attention that you suggested the "synchronized decorator" - but I feel this decorator is "too strong" for your needs, as it uses a synchronized and will not diffrentiate between cases of N readers and M writers.


This is because the "standard" Java collections are not thread safe as they are not synchronized. When working with multiple threads accessing your collections, you should look at the java.util.concurrent packages.

Without this package, before Java 5, one had to perform a manual synchronization :

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

or using

Collections.synchronizedList(arrayList);

but neither could really offer a complete thread safety feature.

With this package, all access to the collection is made atomically and some classes provide a snapshot of the state of the list when the iterator was constructed (see CopyOnWriteArrayList . The CopyOnWriteArrayList is fast on read, but if you are performing many writes, this might affect performance.

Thus, if CopyOnWriteArrayList is not desired, take a look at ConcurrentLinkedQueue which offers a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator . This one is efficient in all point, unless you have to access elements at specific indexes more often than traversing the entire collection.

Another option would be ConcurrentSkipListSet which 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 and iterators are weakly consistent as well.

Which concurrent (thread-safe) collections depend of what type of operations you perform the most with. And since they are all part of the Java Collection framework, you can swap them to which ever you need.

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

上一篇: 如何给iPhone中的图片提供自定义名称

下一篇: 如何避免ConcurrentModificationException