在现代JVM中双重检查锁定

Swa*_*rma 4 java multithreading synchronization

我有一个类可能会在初始化期间抛出任何运行时异常.我希望这个类是一个单例,因为在内存中保存多个对象的成本很高.我在另一堂课中使用那门课.

我的用例如下:

  • 我必须使用单个实例Controller.
  • 每个实例Parent必须使用相同的Controller实例.
  • Controller 构造函数可能会抛出异常.
  • 如果实例化失败,我应该在一段时间后重试实例化.

所以我检查我的Controller实例是否null在我尝试对其进行"获取"时Controller,如果是,我会尝试再次实例化它.

以下是我的代码:

class Parent
{
    private static volatile Controller controller;
    private static final Object lock = new Object();

    static
    {
        try
        {
            controller = new Controller();
        }
        catch(Exception ex)
        {
            controller = null;
        }
    }

    private Controller getController() throws ControllerInstantiationException
    {
        if(controller == null)
        {
            synchronized(lock)
            {
                if(controller == null)
                {
                    try
                    {
                        controller = new Controller();
                    }
                    catch(Exception ex)
                    {
                        controller = null;
                        throw new ControllerInstatntationException(ex);
                    }
                }
            }
        }
        return controller;
    }

    //other methods that uses getController() 
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,这段代码坏了吗?我在某处读到上述代码在JVM 1.4或更早版本中会出现问题.你能提供参考/解决方案吗?请注意,我问这个问题,因为互联网上有很多关于这个主题的混淆.

谢谢.

Ant*_*ton 5

我相信它没有被破坏,是volatile宣言的原因.但是imho最好避免像这样的代码.无法保证此代码适用于Java 8.还有另一种方法来创建懒惰的单身人士.我总是(差不多)使用这种方法.第一次在Java Concurrency in Practice一书中面对它.

public class Singleton {
        private Singleton() { }

        private static class SingletonHolder { 
                public static final Singleton instance = new Singleton();
        }

        public static Singleton getInstance() {
                return SingletonHolder.instance;
        }
}
Run Code Online (Sandbox Code Playgroud)

我不知道你在代码中做了什么,很难说,如何调整它.最简单的方法,只需使用synchronize方法.您是否真的希望使用双重检查锁定获得一些性能优势?是否有瓶颈同步方法?