diff --git a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java index 6ebf36c859..9374bafe79 100644 --- a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java +++ b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java @@ -24,6 +24,8 @@ import java.sql.SQLException; import java.sql.Savepoint; import java.util.Date; import java.util.Properties; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import com.alibaba.druid.filter.Filter; import com.alibaba.druid.filter.FilterChain; @@ -69,6 +71,8 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { public final static String ATTR_TRANSACTION = "stat.tx"; public final static String ATTR_RESULTSET_CLOSED = "stat.rs.closed"; + private final Lock lock = new ReentrantLock(); + // protected JdbcDataSourceStat dataSourceStat; @Deprecated @@ -151,13 +155,18 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { } @Override - public synchronized void init(DataSourceProxy dataSource) { - if (this.dbType == null || this.dbType.trim().length() == 0) { - this.dbType = dataSource.getDbType(); - } + public void init(DataSourceProxy dataSource) { + lock.lock(); + try { + if (this.dbType == null || this.dbType.trim().length() == 0) { + this.dbType = dataSource.getDbType(); + } - configFromProperties(dataSource.getConnectProperties()); - configFromProperties(System.getProperties()); + configFromProperties(dataSource.getConnectProperties()); + configFromProperties(System.getProperties()); + } finally { + lock.unlock(); + } } public void configFromProperties(Properties properties) { diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 41d802353b..79b3e5ae1d 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -231,6 +231,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements protected Condition notEmpty; protected Condition empty; + protected ReentrantLock activeConnectionLock = new ReentrantLock(); + protected AtomicLong createCount = new AtomicLong(); protected AtomicLong destroyCount = new AtomicLong(); @@ -1372,8 +1374,11 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements } public Set getActiveConnections() { - synchronized (activeConnections) { + activeConnectionLock.lock(); + try { return new HashSet(this.activeConnections.keySet()); + } finally { + activeConnectionLock.unlock(); } } diff --git a/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java b/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java index 10cf4f79a6..9c485e7a29 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java +++ b/src/main/java/com/alibaba/druid/pool/DruidConnectionHolder.java @@ -35,6 +35,7 @@ import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.locks.ReentrantLock; /** * @author wenshao [szujobs@hotmail.com] diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index f83d895a28..7a263f7514 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -1007,7 +1007,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER) // || realDriverClassName.equals(JdbcConstants.MYSQL_DRIVER_6)) { this.validConnectionChecker = new MySqlValidConnectionChecker(); - } else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER)) { + } else if (realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER) + || realDriverClassName.equals(JdbcConstants.ORACLE_DRIVER2)) { this.validConnectionChecker = new OracleValidConnectionChecker(); } else if (realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER) || realDriverClassName.equals(JdbcConstants.SQL_SERVER_DRIVER_SQLJDBC4) @@ -1141,8 +1142,11 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat poolableConnection.setConnectedTimeNano(); poolableConnection.setTraceEnable(true); - synchronized (activeConnections) { + activeConnectionLock.lock(); + try { activeConnections.put(poolableConnection, PRESENT); + } finally { + activeConnectionLock.unlock(); } } @@ -1289,21 +1293,28 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat // exceptionSorter.isExceptionFatal if (exceptionSorter != null && exceptionSorter.isExceptionFatal(sqlEx)) { if (pooledConnection.isTraceEnable()) { - synchronized (activeConnections) { + activeConnectionLock.lock(); + try { if (pooledConnection.isTraceEnable()) { activeConnections.remove(pooledConnection); pooledConnection.setTraceEnable(false); } + } finally { + activeConnectionLock.unlock(); } } boolean requireDiscard = false; - synchronized (pooledConnection) { + final ReentrantLock lock = pooledConnection.lock; + lock.lock(); + try { if ((!pooledConnection.isClosed()) || !pooledConnection.isDisable()) { holder.setDiscard(true); pooledConnection.disable(t); requireDiscard = true; } + } finally { + lock.unlock(); } if (requireDiscard) { @@ -1341,16 +1352,20 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat final Connection physicalConnection = holder.getConnection(); if (pooledConnection.isTraceEnable()) { - synchronized (activeConnections) { + Object oldInfo = null; + activeConnectionLock.lock(); + try { if (pooledConnection.isTraceEnable()) { - Object oldInfo = activeConnections.remove(pooledConnection); - if (oldInfo == null) { - if (LOG.isWarnEnabled()) { - LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size()); - } - } + oldInfo = activeConnections.remove(pooledConnection); pooledConnection.setTraceEnable(false); } + } finally { + activeConnectionLock.unlock(); + } + if (oldInfo == null) { + if (LOG.isWarnEnabled()) { + LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size()); + } } } @@ -1367,8 +1382,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat // reset holder, restore default settings, clear warnings boolean isSameThread = pooledConnection.getOwnerThread() == Thread.currentThread(); if (!isSameThread) { - synchronized (pooledConnection) { + final ReentrantLock lock = pooledConnection.lock; + lock.lock(); + try { holder.reset(); + } finally { + lock.unlock(); } } else { holder.reset(); @@ -2212,7 +2231,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat List abandonedList = new ArrayList(); - synchronized (activeConnections) { + activeConnectionLock.lock(); + try { Iterator iter = activeConnections.keySet().iterator(); for (; iter.hasNext();) { @@ -2230,14 +2250,20 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat abandonedList.add(pooledConnection); } } + } finally { + activeConnectionLock.unlock(); } if (abandonedList.size() > 0) { for (DruidPooledConnection pooledConnection : abandonedList) { - synchronized (pooledConnection) { + final ReentrantLock lock = pooledConnection.lock; + lock.lock(); + try { if (pooledConnection.isDisable()) { continue; } + } finally { + lock.unlock(); } JdbcUtils.close(pooledConnection); diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java index 2f95d12309..07a325c2f3 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java @@ -35,6 +35,8 @@ import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; @@ -75,6 +77,8 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql. private Throwable disableError = null; + public ReentrantLock lock = new ReentrantLock(); + public DruidPooledConnection(DruidConnectionHolder holder){ super(holder.getConnection()); @@ -258,33 +262,38 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql. this.disable = true; } - public synchronized void syncClose() throws SQLException { - if (this.disable) { - return; - } - - DruidConnectionHolder holder = this.holder; - if (holder == null) { - if (dupCloseLogEnable) { - LOG.error("dup close"); + public void syncClose() throws SQLException { + lock.lock(); + try { + if (this.disable) { + return; } - return; - } - for (ConnectionEventListener listener : holder.getConnectionEventListeners()) { - listener.connectionClosed(new ConnectionEvent(this)); - } + DruidConnectionHolder holder = this.holder; + if (holder == null) { + if (dupCloseLogEnable) { + LOG.error("dup close"); + } + return; + } - DruidAbstractDataSource dataSource = holder.getDataSource(); - List filters = dataSource.getProxyFilters(); - if (filters.size() > 0) { - FilterChainImpl filterChain = new FilterChainImpl(dataSource); - filterChain.dataSource_recycle(this); - } else { - recycle(); - } + for (ConnectionEventListener listener : holder.getConnectionEventListeners()) { + listener.connectionClosed(new ConnectionEvent(this)); + } - this.disable = true; + DruidAbstractDataSource dataSource = holder.getDataSource(); + List filters = dataSource.getProxyFilters(); + if (filters.size() > 0) { + FilterChainImpl filterChain = new FilterChainImpl(dataSource); + filterChain.dataSource_recycle(this); + } else { + recycle(); + } + + this.disable = true; + } finally { + lock.unlock(); + } } public void recycle() throws SQLException { @@ -1106,8 +1115,11 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql. } if (asyncCloseEnabled) { - synchronized (this) { + lock.lock(); + try { checkStateInternal(); + } finally { + lock.unlock(); } } else { checkStateInternal(); diff --git a/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatManager.java b/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatManager.java index e51d4b8782..fa700dbde7 100644 --- a/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatManager.java +++ b/src/main/java/com/alibaba/druid/stat/DruidDataSourceStatManager.java @@ -23,6 +23,8 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import javax.management.JMException; import javax.management.MBeanServer; @@ -44,6 +46,8 @@ import com.alibaba.druid.util.JMXUtils; @SuppressWarnings("rawtypes") public class DruidDataSourceStatManager implements DruidDataSourceStatManagerMBean { + private final static Lock staticLock = new ReentrantLock(); + public final static String SYS_PROP_INSTANCES = "druid.dataSources"; public final static String SYS_PROP_REGISTER_SYS_PROPERTY = "druid.registerToSysProperty"; @@ -62,23 +66,28 @@ public class DruidDataSourceStatManager implements DruidDataSourceStatManagerMBe return instance; } - public synchronized static void clear() { - Map dataSources = getInstances(); + public static void clear() { + staticLock.lock(); + try { + Map dataSources = getInstances(); - MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); - for (Object item : dataSources.entrySet()) { - Map.Entry entry = (Map.Entry) item; - ObjectName objectName = (ObjectName) entry.getValue(); + MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); + for (Object item : dataSources.entrySet()) { + Map.Entry entry = (Map.Entry) item; + ObjectName objectName = (ObjectName) entry.getValue(); - if (objectName == null) { - continue; - } + if (objectName == null) { + continue; + } - try { - mbeanServer.unregisterMBean(objectName); - } catch (JMException e) { - LOG.error(e.getMessage(), e); + try { + mbeanServer.unregisterMBean(objectName); + } catch (JMException e) { + LOG.error(e.getMessage(), e); + } } + } finally { + staticLock.unlock(); } } @@ -86,7 +95,8 @@ public class DruidDataSourceStatManager implements DruidDataSourceStatManagerMBe public static Map getInstances() { Map tmp = dataSources; if (tmp == null) { - synchronized (DruidDataSourceStatManager.class) { + staticLock.lock(); + try { if (isRegisterToSystemProperty()) { dataSources = getInstances0(); } else { @@ -95,6 +105,8 @@ public class DruidDataSourceStatManager implements DruidDataSourceStatManagerMBe dataSources = tmp = Collections.synchronizedMap(new IdentityHashMap()); } } + } finally { + staticLock.unlock(); } }