我偶然碰到了一篇文章,该文章最近讨论了Java中的双重检查锁定模式及其陷阱,现在我想知道我多年来使用的这种模式的变体是否会遇到任何问题。

我看过许多关于该主题的文章和文章,并了解了对部分构造的对象的引用所带来的潜在问题,据我所知,我认为我的实现不受这些问题的影响。以下模式是否有问题?

而且,如果没有,人们为什么不使用它呢?在围绕该问题进行的任何讨论中,我从未见过推荐它的方法。

public class Test {
    private static Test instance;
    private static boolean initialized = false;

    public static Test getInstance() {
        if (!initialized) {
            synchronized (Test.class) {
                if (!initialized) {
                    instance = new Test();
                    initialized = true;
                }
            }
        }
        return instance;
    }
}

最佳答案

Double check locking is broken。由于初始化是原语,因此它可能不需要 volatile 即可工作,但是在实例初始化之前,没有什么可以阻止初始化被视为对非同步代码是正确的。

编辑:为了澄清上述答案,原始问题询问有关使用 boolean 值来控制双重检查锁定的问题。如果没有以上链接中的解决方案,它将无法正常工作。您可以仔细检查锁,实际上是设置了一个 boolean 值,但是在创建类实例时,仍然存在有关指令重新排序的问题。建议的解决方案不起作用,因为在非同步块(synchronized block)中看到已初始化的 boolean 值为true后,实例可能未初始化。

仔细检查锁定的正确解决方案是使用volatile(在实例字段上)并忽略初始化的 boolean 值,并确保使用JDK 1.5或更高版本,或者在最终字段中对其进行初始化(如链接中所述)文章和汤姆的答案,或者就是不使用它。

当然,整个概念似乎是一个巨大的过早优化,除非您知道在获取此Singleton时将引起大量线程争用,或者您已经剖析了该应用程序并将其视为热点。

关于java - Java双重检查锁定,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1625118/

10-08 22:38