Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference in behavior between these two usages of synchronized on a list

List<String> list = new ArrayList<String>();
list.add("a");
...
list.add("z");

synchronized(list) {
    Iterator<String> i = list.iterator();
    while(i.hasNext()) {
        ...
    }
}

and

List<String> list = new ArrayList<String>();
list.add("a");
...
list.add("z");

List<String> synchronizedList = Collections.synchronizedList(list);

synchronized(synchronizedList) {
    Iterator<String> i = synchronizedList.iterator();
    while(i.hasNext()) {
        ...
    }
}

Specifically, I'm not clear as to why synchronized is required in the second instance when a synchronized list provides thread-safe access to the list.

like image 761
Vivin Paliath Avatar asked Aug 29 '12 16:08

Vivin Paliath


1 Answers

If you don't lock around the iteration, you will get a ConcurrentModificationException if another thread modifies it during the loop.

Synchronizing all of the methods doesn't prevent that in the slightest.

This (and many other things) is why Collections.synchronized* is completely useless.
You should use the classes in java.util.concurrent. (and you should think carefully about how you will guarantee you will be safe)

As a general rule of thumb:

Slapping locks around every method is not enough to make something thread-safe.

For much more information, see my blog

like image 145
SLaks Avatar answered Sep 19 '22 16:09

SLaks