My quick read of this change is not favorable. It looks like changes to an unsynchronized list have been moved outside any synchronization. Also integer math like numActive++ outside a synchronization block has got me into problems in the past. A test with two threads using i++ and i-- ran quite some time (couple hours) on a single processor box, but did eventually fail. Then the test was run on a dual processor box, it failed pretty much immediately, repeatedly.
I'm -1 on this change. john mcnally On Wed, 2003-08-13 at 05:42, [EMAIL PROTECTED] wrote: > dirkv 2003/08/13 05:42:28 > > Modified: pool/src/java/org/apache/commons/pool/impl > GenericObjectPool.java > Log: > Bugzilla Bug 19614: [DBCP] Poor performance under load > Bugzilla Bug 22229: [DBCP] Foul connection causes livelock of all pool operations > > - remove synchronization on borrowObject > > Revision Changes Path > 1.22 +76 -27 > jakarta-commons/pool/src/java/org/apache/commons/pool/impl/GenericObjectPool.java > > Index: GenericObjectPool.java > =================================================================== > RCS file: > /home/cvs/jakarta-commons/pool/src/java/org/apache/commons/pool/impl/GenericObjectPool.java,v > retrieving revision 1.21 > retrieving revision 1.22 > diff -u -r1.21 -r1.22 > --- GenericObjectPool.java 12 Aug 2003 22:46:09 -0000 1.21 > +++ GenericObjectPool.java 13 Aug 2003 12:42:28 -0000 1.22 > @@ -163,6 +163,7 @@ > * > * @see GenericKeyedObjectPool > * @author Rodney Waldhoff > + * @author Dirk Verbeeck > * @version $Revision$ $Date$ > */ > public class GenericObjectPool extends BaseObjectPool implements ObjectPool { > @@ -705,65 +706,113 @@ > > //-- ObjectPool methods ------------------------------------------ > > - public synchronized Object borrowObject() throws Exception { > + public Object borrowObject() throws Exception { > + // Warning: because the method synchonization is gone > + // _numActive should be incremented as soon as possible > + // otherwise the pool can go over the limit > + // decrement on error (do not forget to notifyAll) > + > assertOpen(); > long starttime = System.currentTimeMillis(); > boolean newlyCreated = false; > for(;;) { > ObjectTimestampPair pair = null; > // if there are any sleeping, just grab one of those > - try { > - pair = (ObjectTimestampPair)(_pool.removeFirst()); > - } catch(NoSuchElementException e) { > - ; /* ignored */ > + if (!_pool.isEmpty()) { // no need to synchronize when pool is empty > + synchronized(this) { > + try { > + _numActive++; > + pair = (ObjectTimestampPair)(_pool.removeFirst()); > + } catch(NoSuchElementException e) { > + ; /* ignored */ > + } > + if(null == pair) { // someone took the last one before us > + _numActive--; > + notifyAll(); > + } > + } > } > // otherwise > if(null == pair) { > // check if we can create one > // (note we know that the num sleeping is 0, else we wouldn't be > here) > if(_maxActive <= 0 || _numActive < _maxActive) { > - Object obj = _factory.makeObject(); > - pair = new ObjectTimestampPair(obj); > - newlyCreated = true; > + try { > + _numActive++; > + Object obj = _factory.makeObject(); > + pair = new ObjectTimestampPair(obj); > + newlyCreated = true; > + } > + finally { > + if(null == pair) { > + synchronized(this) { > + _numActive--; > + notifyAll(); > + } > + } > + } > } else { > // the pool is exhausted > switch(_whenExhaustedAction) { > case WHEN_EXHAUSTED_GROW: > - Object obj = _factory.makeObject(); > - pair = new ObjectTimestampPair(obj); > + try { > + _numActive++; > + Object obj = _factory.makeObject(); > + pair = new ObjectTimestampPair(obj); > + newlyCreated = true; > + } > + finally { > + if(null == pair) { > + synchronized(this) { > + _numActive--; > + notifyAll(); > + } > + } > + } > break; > case WHEN_EXHAUSTED_FAIL: > throw new NoSuchElementException(); > case WHEN_EXHAUSTED_BLOCK: > - try { > - if(_maxWait <= 0) { > - wait(); > + synchronized(this) { > + // only sleep when the pool is really empty > + // between the isEmpty check at the beginning > + // and here, an object could have been added > + // to the pool > + if (_pool.isEmpty()) { > + try { > + if(_maxWait <= 0) { > + wait(); > + } else { > + wait(_maxWait); > + } > + } catch(InterruptedException e) { > + // ignored > + } > + } > + if(_maxWait > 0 && ((System.currentTimeMillis() - > starttime) >= _maxWait)) { > + throw new NoSuchElementException("Timeout > waiting for idle object"); > } else { > - wait(_maxWait); > + continue; // keep looping > } > - } catch(InterruptedException e) { > - // ignored > - } > - if(_maxWait > 0 && ((System.currentTimeMillis() - > starttime) >= _maxWait)) { > - throw new NoSuchElementException("Timeout waiting > for idle object"); > - } else { > - continue; // keep looping > } > default: > throw new > IllegalArgumentException("whenExhaustedAction " + _whenExhaustedAction + " not > recognized."); > } > } > } > - > try { > _factory.activateObject(pair.value); > if(_testOnBorrow && !_factory.validateObject(pair.value)) { > throw new Exception("validateObject failed"); > } > - _numActive++; > return pair.value; > } > catch (Exception e) { > + // object cannot be activated or is invalid > + synchronized(this) { > + _numActive--; > + notifyAll(); > + } > try { > _factory.destroyObject(pair.value); > } > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]