Codievilky August created POOL-391: -------------------------------------- Summary: GenericKeyedObjectPool is not thread safe when invoke method `borrowObject` and `destroy` simultaneously Key: POOL-391 URL: https://issues.apache.org/jira/browse/POOL-391 Project: Commons Pool Issue Type: Bug Affects Versions: 2.9.0, 2.8.0, 2.7.0, 2.6.0, 2.5.0, 2.4.2 Reporter: Codievilky August
The method `brrowObject` is not thread safe with `destroy` or `clear` method. The reason is when use GenericKeyedObjectPool#destroy method,it did not ensure the *Atomicity* of destroy object from the ObjectDeque。 This may cause in the GenericKeyedObjectPool#borrowObject method,may get the wrong number of GenericKeyedObjectPool.ObjectDeque#getCreateCount when need to create. And the GenericKeyedObjectPool#borrowObject will block until timeout. Here is the sample test code to recur the bug: {code:java} // code placeholder public class CommonPoolMultiThreadTest { public static void main(String[] args) { GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig(); config.setMaxTotalPerKey(1); config.setMinIdlePerKey(0); config.setMaxIdlePerKey(-1); config.setMaxTotal(-1); config.setMaxWaitMillis(TimeUnit.SECONDS.toMillis(5)); GenericKeyedObjectPool<Integer, Integer> testPool = new GenericKeyedObjectPool<>( new KeyedPooledObjectFactory<Integer, Integer>() { @Override public PooledObject<Integer> makeObject(Integer key) throws Exception { System.out.println("start to create"); return new DefaultPooledObject<>(10); } @Override public void destroyObject(Integer key, PooledObject<Integer> p) throws Exception { System.out.println("start to destroy"); Thread.sleep(2000); } @Override public boolean validateObject(Integer key, PooledObject<Integer> p) { return true; } @Override public void activateObject(Integer key, PooledObject<Integer> p) throws Exception { // do nothing } @Override public void passivateObject(Integer key, PooledObject<Integer> p) throws Exception { // do nothing } }, config ); int borrowKey = 10; Thread t = new Thread(() -> { try { while (true) { testPool.borrowObject(borrowKey); Thread.sleep(10); } } catch (Exception e) { e.printStackTrace(); System.exit(1); } }); Thread t2 = new Thread(() -> { try { while (true) { testPool.clear(borrowKey); Thread.sleep(10); } } catch (Exception e) { e.printStackTrace(); System.exit(1); } }); t.start(); t2.start(); } } {code} -- This message was sent by Atlassian Jira (v8.3.4#803005)