[ 
https://issues.apache.org/jira/browse/POOL-391?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17442354#comment-17442354
 ] 

Phil Steitz commented on POOL-391:
----------------------------------

A fix for this is in [https://github.com/apache/commons-pool/pull/113]

The lack of "atomicity" is by design, to avoid synchronization delays waiting 
for creates to complete.  Other public methods that create capacity (return, 
invalidate, evict, etc) call reuseCapacity, which allocates freed capacity to 
pools that have borrowers waiting.  The PR modifies clear() to (optionally) do 
this.  

> 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.4.2, 2.5.0, 2.6.0, 2.7.0, 2.8.0, 2.9.0
>            Reporter: Codievilky August
>            Priority: Blocker
>   Original Estimate: 24h
>  Remaining Estimate: 24h
>
> 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) {
>           Integer integer = testPool.borrowObject(borrowKey);
>           testPool.returnObject(borrowKey, integer);
>           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.20.1#820001)

Reply via email to