Java双锁 - 有人可以更简单地解释为什么直觉不会工作? [英] Java Double Locking - Can someone explain more simply why intuition wouldn't work?

查看:117
本文介绍了Java双锁 - 有人可以更简单地解释为什么直觉不会工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里找到了以下代码: http://en.wikipedia.org/wiki / Double-checked_locking#Usage_in_Java

I found the following code here: http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java

我想了解为什么在某些情况下这不会工作。我读了关于微妙问题的解释,使用 volatile 将解决这个问题,但我有点困惑。

I am trying to understand why there are certain cases where this would not work. I read the explanation of the "subtle" problems, and that using volatile will fix the issue, but I'm a bit confused.

// Broken multithreaded version
// "Double-Checked Locking" idiom
class Foo {
    private Helper helper = null;
    public Helper getHelper() {
        if (helper == null) {
            synchronized(this) {
                if (helper == null) {
                    helper = new Helper();
                }
            }
        }
        return helper;
    }

    // other functions and members...
}


b $ b

基本上,我可以认为这将失败,因为 helper == null 检查同步块有机会失败,因为它可以部分构建在那一点?如果对象是部分构造的,java 不是返回null?这是问题吗?

Basically, am I right to assume this would fail due to the fact that the helper == null check in the synchronized block has a chance to fail because it could be "partially" constructed at that point? Does java not return null if an object is partially constructed? Is that the issue?

无论如何,我知道这不是伟大的做法做双重检查锁定,但我只是奇怪为什么上述代码失败,为什么volatile(加上添加一个局部变量)修复这个?

Anyway, I know that it's not great practice to do double check locking, but I was just curious in theory why the above code fails, and why volatile (plus the addition of assigning a local variable) fixes this? Here's some code I got from somewhere.

// Double-check idiom for lazy initialization of instance fields
private volatile FieldType field;
FieldType getField() {
    FieldType result = field;
    if (result == null) { // First check (no locking)
        synchronized(this) {
            result = field;
            if (result == null) // Second check (with locking)
                field = result = computeFieldValue();
        }
    }
    return result;
}

我知道已经有了一千个帖子,内存模型的变化在1.5之后,我不太明白它与它有什么关系: - (。

I know there are a thousand posts already about this, but explanations seem to mention changes in memory model after 1.5, and I don't quite get what that has to do with it too :-(.

感谢高级!

推荐答案


我是正确的假设这将失败,因为helper == null检查同步块有机会失败,因为它可以在这一点上部分构建?

am I right to assume this would fail due to the fact that the helper == null check in the synchronized block has a chance to fail because it could be "partially" constructed at that point?

是的, a href =http://www.ibm.com/developerworks/java/library/j-dcl/index.html =nofollow>乱序写入。 helper = new Helper()由3个步骤组成:内存分配,调用构造函数和赋值JIT编译器可以自由重新排序指令,并在内存分配后返回引用对象),但在构造函数调用之前。使用volatile防止重新排序。

Yes you are right. This is explained in Out-of-order writes. helper = new Helper() consists of 3 steps: memory allocation, call to the constructor, and assignment. JIT compiler is free to reorder instructions and do assignment after memory allocation (which returns reference to the new object) but before the constructor invocation. Using volatile prevents reordering.

这篇关于Java双锁 - 有人可以更简单地解释为什么直觉不会工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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