易失性参考并随后设置变量的值

时间:2016-08-22 07:34:21

标签: java

考虑一下代码段:

class Mutable {
    private volatile int value;
    public int get()
    {
        return value;
    }
    public int set(int value)
    {
        this.value = value;
    }
}

class Test {
    public volatile Mutable m;
}

所以使用以下序列:

Thread-1: get()     // returns 2
Thread-2: set(3)
Thread-1: get()     // guaranteed to return 3 due to volatile with property value

但我无法理解作者的以下注释 -

  但是,一个注释,当分配m时,内部值将是   正确可见。 只有在后续调用set()之后才会这样做   不写你有问题

请举例说明。他在谈论哪个问题?

2 个答案:

答案 0 :(得分:3)

因此,上次评论令人困惑的原因是因为它脱离了背景。您提供的示例代码与该评论所针对的original code不同。在原始代码中,value 不是 volatile。如果value不易变,则会出现以下情况。

线程1:

Mutable tmp = new Mutable();
tmp.set(3);
Test.m = tmp;

线程2:

Test.m.get();  // *** this is guaranteed to return 3 due to the happens before rules.

线程1:

Test.m.set(5);

线程2:

Test.m.get();  // no guaranatees here, could be 3, could be 5

我的评论指的是" ***"部分,m的不稳定分配提供了在关系之前发生的事情,这使得" 3"对Thread2可见(由于m的易失性读取)。 (为了重新迭代,value在这个例子中不易变。)

答案 1 :(得分:1)

我相信,有问题的部分是volatile保证了读写访问之前发生的关系。我们只是不知道快速写操作符会发生什么:

Thread-1: get()     // returns 2

// no real happens-before on the 3 lines below:
Thread-2: set(3)
Thread-3: set(4)
Thread-4: set(5)

// now what?
Thread-1: get()     // guaranteed to return 3 or 4 or 5 due to volatile with property value

一个更棘手的案例是增加一个计数器:

Thread-1: get()     // returns 2

// no real happens-before on the 3 lines below. They all might increment the 2:
Thread-2: set(get()+1)
Thread-3: set(get()+1)
Thread-4: set(get()+1)

// now what?
Thread-1: get()     // guaranteed to return 3 or 4 or 5 due to volatile with property value