Recently I came across a code which gave a false sense of synchronization guarantee. Also this code reminded me how easy it is to forget about JVM byte code translations.
Issue was a synchronized list was being populated in one thread and accessed through another. For simplicity reasons, following code could be treated as a similar example (few threads updates the list and others iterate over it):
Side effect would have caused list corruption (update by one thread while in use by another thread. Also this issue can also be confirmed through test case (Iterators are fail fast and with an unlucky timing would result in ConcurrentModificationException)
Few noteworthy things besides the synchronization issue:
1) "For-each Loop" construct introduced in Java 5 gets translated into Iterator.
2) String concatenation using "+" operator gets translated to "new StringBuilder.append()...append().toString()".
Issue was a synchronized list was being populated in one thread and accessed through another. For simplicity reasons, following code could be treated as a similar example (few threads updates the list and others iterate over it):
List<String> list = new ArrayList<String>(); list = Collections.synchronizedList(list); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.add("e"); for (String temp: list) { System.out.println("value:"+temp); }Do you think above code would give synchronization guarantee when iterating in the loop? No, it wont. I am not doubting the synchronization policy on list operations (add, get, delete, etc) but over its element iteration. To prove the case, get a decompiler (eg: jad) and from the class file reconstruct the java file. Below is the snapshot of the same.
Above snapshot confirms that there is no synchronization taking place during iteration. Changed the code to following to enforce synchronization (alternatively can use JAVA 6, concurrent variant CopyOnWriteArrayList):
List<String> list = new ArrayList<String>(); list = Collections.synchronizedList(list); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.add("e"); synchronized (list) { for (String temp: list) { System.out.println("value:"+temp); } }Below snapshot confirms (decompiled version) the enforcement (check for monitorenter):
Side effect would have caused list corruption (update by one thread while in use by another thread. Also this issue can also be confirmed through test case (Iterators are fail fast and with an unlucky timing would result in ConcurrentModificationException)
Few noteworthy things besides the synchronization issue:
1) "For-each Loop" construct introduced in Java 5 gets translated into Iterator.
2) String concatenation using "+" operator gets translated to "new StringBuilder.append()...append().toString()".
No comments:
Post a Comment