Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java synchronized list for loop

Documentation on synchronizedList states that,

It is imperative that the user manually synchronize on the returned list when iterating over it:

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

Failure to follow this advice may result in non-deterministic behavior.

This seems pretty clear, but I just wanted to confirm that a for each loop is prohibited. For example, I cannot do something like as follows right?

List<MyType> list = Collections.synchronizedList(new ArrayList(<MyType>));
...
synchronized(list){
    for(MyType m : list){
        foo(m);
        m.doSomething();
    }
}
like image 599
user927476 Avatar asked Sep 07 '11 14:09

user927476


3 Answers

Yes, you can - your enhanced for loop is basically the same as your code which explicitly uses the iterator. It boils down to the same code - it's just calling iterator() and then alternating between next() and hasNext() calls.

like image 121
Jon Skeet Avatar answered Nov 07 '22 14:11

Jon Skeet


You can do that. The foreach loop compiles to (nearly) the same bytecode as the while loop. The keys are:

  1. You synchronize the block around the loop because the list may change while you are iterating over it.
  2. You use the list as the object that you are synchronizing on, since the implementation of this class locks on itself (through synchronized methods).
like image 1
Ryan Gross Avatar answered Nov 07 '22 14:11

Ryan Gross


If possible, you might want to consider using immutability rather than synchonization.

http://docs.guava-libraries.googlecode.com/git-history/release09/javadoc/com/google/common/collect/ImmutableList.html

like image 1
John B Avatar answered Nov 07 '22 15:11

John B