Details
Description
Hi,
I get a ConcurrentModificationException when using instances of SharedPoolDataSource concurrently. The problem occurs when one thread calls setDataSourceName() while another thread calls close(), either on the same instance of SharedPoolDataSource or on different instances. I'll attach a short example program that leads to an exception for almost every run on my machine.
The cause of the exception seems to be in InstanceKeyObjectFactory. registerNewInstance() is synchronized, but removeInstance() isn't. This allows concurrent accesses to the non-thread-safe 'instanceMap'.
Is this a bug? Or are SharedPoolDataSource and InstanceKeyObjectFactory not supposed to be thread-safe?
Thanks!
import java.util.ArrayList;
import org.apache.commons.dbcp.datasources.SharedPoolDataSource;
public class SharedPoolDataSourceTest {
public static void main(String[] args)
{ new SharedPoolDataSourceTest().run(); } private void run() {
final ArrayList<SharedPoolDataSource> dataSources = new ArrayList<SharedPoolDataSource>();
for (int j = 0; j < 10000; j++)
Thread t1 = new Thread(new Runnable() {
public void run() {
for (SharedPoolDataSource dataSource : dataSources)
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
for (SharedPoolDataSource dataSource : dataSources) {
try
catch (Exception e) {}
}
}
});
t1.start();
t2.start();
try
catch (InterruptedException ie) {}
}
}
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
at java.util.HashMap$KeyIterator.next(HashMap.java:828)
at org.apache.commons.dbcp.datasources.InstanceKeyObjectFactory.registerNewInstance(InstanceKeyObjectFactory.java:51)
at org.apache.commons.dbcp.datasources.InstanceKeyDataSource.setDataSourceName(InstanceKeyDataSource.java:246)
at potentialBugs.SharedPoolDataSourceTest$1.run(SharedPoolDataSourceTest.java:23)
at java.lang.Thread.run(Thread.java:619)