Reputation: 1655
List<Ball> myObjs = myThreads[threadIndex].getMyObjList();
int initialSize = Collections.synchronizedList(myObjs).size();
Throws ConcurrentModificationException. I have also tried putting this in a synchronized(myObjs) block, but it also didn't work. What is the solution? Everywhere else where I use this list, it is in an synchronized(block).
P.S. This error also ends up producing BrokenBarrierException. (yes, I am using cyclic barrier for synchronization)
EDIT: Here is the stack trace:
Exception in thread "Thread-3" java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1091)
at java.util.ArrayList$SubList.size(ArrayList.java:921)
at java.util.Collections$SynchronizedCollection.size(Collections.java:1573)
at Part2.Animation.processCollisions(MyClass.java:133) // This is the call to size()
EDIT: The loop looks like
for (int threadIndex=0; threadIndex < numThreads; threadIndex++) {
List<Ball> myObjs = myThreads[threadIndex].getMyObjList();
int initialSize = Collections.synchronizedList(myObjs).size();
}
And regardless of numThreads, the exception happens when threadIndex=1.
Upvotes: 2
Views: 1863
Reputation: 32014
It's caused by subList()
, has nothing to do with synchronize.
myObjs
is a result of subList(), actually myObjs is view of original List. If the original List is modified, ConcurrentModificationException
will happen when subList.size()
is called. It makes sense, view should be consistent to its original List.
Instead, you could get sub list like:
List mySubList = new ArrayList(originalList.subList(a, b));
Upvotes: 2
Reputation: 719149
Looking at the source code for some of the List
classes, I can't see how it is possible that calling size()
will throw a ConcurrentModificationException
. It would help if you showed us a stack trace.
But in the meantime, you appear to have a fundamental misconception about what Collections.synchronizedList
does. What it does is create and return a list wrapper that will ensure that operations on the same wrapper instance are synchronized.
It does not in anyway prevent threads from performing unsynchronized operations on underlying list; i.e. the list object that you just wrapped. If a thread has the reference for the underlying list, it can access it directly without going thrpough the wrapper. And neither does it do anything to synchronize operations using different wrappers for the same underlying list. So if you call Collections.synchronizedList
twice on the same list, you will create two distinct wrappers that do not synchronize with each other.
So, in fact your Collections.synchronizedList(myObjs).size()
does not perform any meaningful synchronization at all. No other thread can get hold of the synchronized list wrapper that is created, so no other thread can synchronize with this one via the wrapper.
Upvotes: 4
Reputation: 479
You should use the CopyOnWriteArrayList
if you want to modify a list with 2 or above threads.
"This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException."
Upvotes: 0