尝试仅创建一个具有多个线程的数据库连接

时间:2014-10-25 15:58:09

标签: java multithreading synchronized locks

public static Database getInstance()
{
    if( instance == null )
    {
        return instanceNotFoundDoubleCheckSynced();
    }
    return instance;
}


synchronized private static Database instanceNotFoundDoubleCheckSynced()
{
    if( instance == null )
    {
        Connection connection = establishConnection();
        if( connection != null )
        {
            instance = new Database( connection );
        }

    }

上面的代码首先尝试获取数据库连接的实例。如果它不能这样做,它会进入同步方法,再次检查,如果仍然没有实例,它将创建一个新的。

我有两个方法检查这个的原因是因为第一个没有同步并且许多线程可以同时运行它,但是我不希望线程运行实际上同时创建新连接的方法。

我的问题是,一旦线程到达instanceNotFoundDoubleCheckSynced方法,他们都会等待机会运行它。

有谁能建议我如何解决这个问题?我不认为这会对生产环境造成问题,因为在建立数据库连接之前不太可能会有这么多的调用,但在我的JUnits中,我有10,000个线程被解雇,它们都被卡住了。

由于

2 个答案:

答案 0 :(得分:0)

你应该避免双重检查锁定,因为它很容易做不到。我认为如果你使用Initialization-on-demand holder idiom会更好,你只需要在内部类中直接实现共享对象。它会更简单,更有效率。

答案 1 :(得分:0)

我认为问题在于您正在测试一个不切实际的场景,其中所有线程都会启动并尝试建立连接。因为a)获得连接需要时间b)有很多线程同时启动,它们都设法通过第一次非同步检查并开始等待同步调用。我建议将测试线程数设置为实际数字(100-200),并在启动线程时添加随机延迟。

此外,您可以将双重检查简化为单个方法并添加正确的错误处理:

class MyClass {

   public static Database getInstance()
   {
       if( instance == null )
       {
           synchronized (MyClass.class) 
           {
             if( instance == null )
             {
                 Connection connection = establishConnection();
                 if( connection == null )
                 {
                     throw new RuntimeException("Cannot establish connection");
                 }
             }

             instance = new Database( connection );
          } 
       }

      return instance;
   }
}

希望这有帮助。

Slava Imeshev