Question: how can the following line of Java code throw the exception shown below?
priv.addAll(common);
Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException at java.lang.System.arraycopy(Native Method) at java.util.ArrayList.toArray(Unknown Source) at java.util.ArrayList.addAll(Unknown Source) at TestConcurrentList$ConsumeThread.run(TestConcurrentList.java:34)
Answer: because of bad synchronization. The scenario is the following: one thread is continuously modifying the list “common” while the second thread tries to perform the “addAll” operation on it. The testcode is shown below:
import java.util.*; public class TestConcurrentList { private static Listcommon = new ArrayList (); private static class GenerateThread extends Thread { private List common; GenerateThread(List common) { this.common = common; } @Override public void run() { while (true) { common.add("foo"); if (common.size() > 1000) common.clear(); } } } private static class ConsumeThread extends Thread { private List common; ConsumeThread(List common) { this.common = common; } @Override public void run() { while (true) { List priv = new ArrayList (); priv.addAll(common); } } } public static void main(String[] args) throws Exception { Thread gen = new GenerateThread(common), consume = new ConsumeThread(common); gen.start(); consume.start(); System.out.println("Waiting..."); gen.join(); } }
What makes this so hard debug is that (a) the exception doesn’t say anything about concurrency (it’s not like it throws an ConcurrentModificationException), (b) the exception actually occurs in the native Java libraries and (c) the source of the concurrent modifications may not be so obvious as in the reduced test case.
Conclusion? When possible, avoid concurrency or delegate it (to an RDBMS with proper transaction / locking support for example).
PS. This bug is not found by FindBugs (admittedly the support for checking concurrency bugs is fairly low at the moment) and is dependent on the version of the runtime. I reproduced it on 1.5.14, but not on 1.6.07.
Picture taken from yimhafiz's photostream with permission.
0 comments:
Post a Comment
You can use some HTML tags, such as <b>, <i>, <a>. Comments are moderated, so there will be a delay until the comment appears. However if you comment, I follow.