getPool方法,也是线程安全的;
public synchronized C3P0PooledConnectionPool getPool(String username, String password, boolean create) throws SQLException
{
if (create)
return getPool( username, password );
else
{
DbAuth checkAuth = new DbAuth( username, password );
C3P0PooledConnectionPool out = (C3P0PooledConnectionPool) authsToPools.get(checkAuth);
if (out == null)
throw new SQLException("No pool has been initialized for databse user '" + username + "' with the specified password.");
else
return out;
}
} 再看
C3P0PooledConnectionPool#checkoutPooledConnection();
public PooledConnection checkoutPooledConnection() throws SQLException
{
//System.err.println(this + " -- CHECKOUT");
try
{
PooledConnection pc = (PooledConnection) this.checkoutAndMarkConnectionInUse();
pc.addConnectionEventListener( cl );
return pc;
}
catch (TimeoutException e)
{ throw SqlUtils.toSQLException("An attempt by a client to checkout a Connection has timed out.", e); }
catch (CannotAcquireResourceException e)
{ throw SqlUtils.toSQLException("Connections could not be acquired from the underlying database!", "08001", e); }
catch (Exception e)
{ throw SqlUtils.toSQLException(e); }
} 返回一个C3P0PooledConnection 实例;C3P0PooledConnection 这个类里的方法都是线程安全的。ComboPooledDataSource@getConnection的最后一站就是C3P0PooledConnection
#getConnection;如下:
public synchronized Connection getConnection()
throws SQLException
{
if ( exposedProxy != null)
{
//DEBUG
//System.err.println("[DOUBLE_GET_TESTER] -- double getting a Connection from " + this );
//new Exception("[DOUBLE_GET_TESTER] -- Double-Get Stack Trace").printStackTrace();
//origGet.printStackTrace();
// System.err.println("c3p0 -- Uh oh... getConnection() was called on a PooledConnection when " +
// "it had already provided a client with a Connection that has not yet been " +
// "closed. This probably indicates a bug in the connection pool!!!");
logger.warning("c3p0 -- Uh oh... getConnection() was called on a PooledConnection when " +
"it had already provided a client with a Connection that has not yet been " +
"closed. This probably indicates a bug in the connection pool!!!");
return exposedProxy;
}
else
{ return getCreateNewConnection(); }
} 从上边的
源码分析可以看出,一个ComboPooledDataSource实例的ComboPooledDataSource@getConnection是线程安全的,可以放心调用;可以测试一下,将最开始的代码稍微修改下,如下:
package com.highgo.test.c3p0deadlock;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
//加锁source个postgre的ComboPooledDataSource的getConnection用一个锁
public class Test {
public static void main(String[] args) throws InterruptedException {
ComboPooledDataSource source = new ComboPooledDataSource("source");
// ComboPooledDataSource source2 = new ComboPooledDataSource("source");
ComboPooledDataSource postgres = new ComboPooledDataSource("postgres");
// ComboPooledDataSource postgres2 = new ComboPooledDataSource("postgres");
new Thread(new SourceGetConn(source), "source").start();
new Thread(new SourceGetConn(source), "source2").start();
// Thread.sleep(1000);
// new Thread(new DestGetConn(postgres), "postgres").start();
// new Thread(new DestGetConn(postgres2), "postgres2").start();
}
}