Trup
Trup

Reputation: 1655

Java - synchronizing getSize() on List

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

Answers (3)

卢声远 Shengyuan Lu
卢声远 Shengyuan Lu

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

Stephen C
Stephen C

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

Ronson
Ronson

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

Related Questions