Java双重检查锁定 [英] Java double checked locking

查看:32
本文介绍了Java双重检查锁定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近看到一篇讨论 Java 中双重检查锁定模式及其陷阱的文章,现在我想知道我多年来一直使用的该模式的变体是否会出现任何问题.

I happened upon an article recently discussing the double checked locking pattern in Java and its pitfalls and now I'm wondering if a variant of that pattern that I've been using for years now is subject to any issues.

我查看了许多关于该主题的帖子和文章,并了解获取对部分构造对象的引用的潜在问题,据我所知,我不认为我的实施受这些问题的影响.以下模式有问题吗?

I've looked at many posts and articles on the subject and understand the potential issues with getting a reference to a partially constructed object, and as far as I can tell, I don't think my implementation is subject to these issues. Are there any issues with the following pattern?

如果没有,人们为什么不使用它?我从未见过在围绕此问题的任何讨论中推荐过它.

And, if not, why don't people use it? I've never seen it recommended in any of the discussion I've seen around this issue.

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. Since initialized is a primitive, it may not require it to be volatile to work, however nothing prevents initialized being seen as true to the non-syncronized code before instance is initialized.

为了澄清上述答案,原始问题询问了使用布尔值来控制双重检查锁定.如果没有上面链接中的解决方案,它将无法工作.您可以仔细检查 lock 实际设置的布尔值,但是在创建类实例时仍然存在指令重新排序的问题.建议的解决方案不起作用,因为在非同步块中看到初始化的布尔值为 true 后,实例可能不会被初始化.

To clarify the above answer, the original question asked about using a boolean to control the double check locking. Without the solutions in the link above, it will not work. You could double check lock actually setting a boolean, but you still have issues about instruction reordering when it comes to creating the class instance. The suggested solution does not work because instance may not be initialized after you see the initialized boolean as true in the non-syncronized block.

仔细检查锁定的正确解决方案是使用 volatile(在实例字段上)并忘记初始化的布尔值,并确保使用 JDK 1.5 或更高版本,或者在最终字段中初始化它,如详细说明在链接的文章和汤姆的回答中,或者干脆不使用它.

The proper solution to double-check locking is to either use volatile (on the instance field) and forget about the initialized boolean, and be sure to be using JDK 1.5 or greater, or initialize it in a final field, as elaborated in the linked article and Tom's answer, or just don't use it.

当然,整个概念似乎是一个巨大的过早优化,除非您知道在获得这个 Singleton 时会遇到大量线程争用,或者您已经对应用程序进行了概要分析并且已经看到这是一个热点.

Certainly the whole concept seems like a huge premature optimization unless you know you are going to get a ton of thread contention on getting this Singleton, or you have profiled the application and have seen this to be a hot spot.

这篇关于Java双重检查锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆