You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Mark Thomas (JIRA)" <ji...@apache.org> on 2011/03/23 19:58:06 UTC

[jira] [Resolved] (POOL-184) Premature starvation in GenericObjectPool when borrowObject() and evict() are executed concurrently

     [ https://issues.apache.org/jira/browse/POOL-184?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Mark Thomas resolved POOL-184.
------------------------------

    Resolution: Fixed
      Assignee: Mark Thomas

As long as the call to allocate() is outside a sync block, you can add as many as you like with the only impact being performance. Inside sync blocks you need to be very careful.

This is fixed in 1.5.x and trunk.

> Premature starvation in GenericObjectPool when borrowObject() and evict() are executed concurrently
> ---------------------------------------------------------------------------------------------------
>
>                 Key: POOL-184
>                 URL: https://issues.apache.org/jira/browse/POOL-184
>             Project: Commons Pool
>          Issue Type: Bug
>    Affects Versions: 1.5.5
>         Environment: java 1.6.0_24
> Ubuntu 10.10
>            Reporter: Adrian Nistor
>            Assignee: Mark Thomas
>             Fix For: 1.5.6
>
>         Attachments: Test01.java, stall.txt
>
>
> Hi,
> I am encountering a deadlock in GenericObjectPool. It appears in version 1.5.5 
> and also in revision 1079385 (March 8th 2011).
> The deadlock manifests when calling borrowObject() and evict() in parallel. I 
> have inlined a test that exposes this problem. For this test, the expected 
> output is:
> Expected output:
> 0
> 1
> 2
> 3
> 4
> .....
> 498
> 499
> DONE
> But when the bug manifests (almost always for this test), the output is:
> Bug output:
> 0
> 1
> 2
> 3
> 4
> When the bug manifests, the test does not finish, it just gets stuck after
> printing several values (in this run: 0 1 2 3 4, but in other runs may be
> 0 1 2 .. 18 or 0 1 2 or some other value).
> When the loop limit is small (e.g., 11 instead of 5000), the test does finish.
> Also, when running sequentially:
>  
>     Pool.borrowObject();
>     Pool.evict();
> or vice-versa
>     Pool.evict();
>     Pool.borrowObject();
> the test still finishes. 
> Is this a bug? Is there a patch for it?
> Thanks!
> Adrian
> ================================================================================
> This test is for version 1.5.5. For revision 1079385 one should replace 
> setMaxActive() with setMaxTotal()
> ================================================================================
> package org.apache.commons.pool.impl;
> import org.apache.commons.pool.PoolableObjectFactory;
> public class Test01 
> {
>     public static void main(String[] args) throws Exception 
>     {
>         Test01 test = new Test01();
>         test.test();
>     }
>     
>     SimpleFactory Factory = null;
>     GenericObjectPool Pool = null;
>     Object Obj = null;
>     public void test() throws Exception 
>     {
>         Factory = new SimpleFactory();
>         Pool = new GenericObjectPool(Factory);
>         Pool.setMaxActive(1);
>         Pool.addObject();
>         
>         for(int i=0; i<5000; i++)
>         {
>             Thread one = new MyThread(1);
>             Thread two = new MyThread(2);
>             one.start();
>             two.start();
>             one.join();
>             two.join();
>             
>             Pool.returnObject(Obj);
>             if(i%10==0)
>             {
>                 System.out.println(i/10);
>             }
>         }
>         System.out.println("DONE");
>     }
>     private class MyThread extends Thread 
>     {
>         int _tid;
>         public MyThread(int tid) 
>         {
>             _tid = tid;
>         }
>         public void run() 
>         {
>             try 
>             {
>                 if(_tid == 1) 
>                 {
>                     Obj = Pool.borrowObject();
>                 }
>                 if (_tid == 2) 
>                 {
>                     try
>                     {
>                         Pool.evict();
>                     } catch (Exception e) {}
>                 }
>             } 
>             catch(Exception e) 
>             {
>                 throw new RuntimeException(e);
>             }
>         }
>     }
>     private class SimpleFactory implements PoolableObjectFactory
>     {
>         public SimpleFactory() {}
>         public Object makeObject() { return new String("testing"); }
>         public void destroyObject(Object obj) {}
>         public boolean validateObject(Object obj) {return true;}
>         public void activateObject(Object obj) throws Exception {}
>         public void passivateObject(Object obj) throws Exception {}
>         public boolean isThrowExceptionOnActivate() {return true;}
>     }
> }
> ================================================================================

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira