顺序一致性易变性解释

时间:2017-10-23 12:37:52

标签: java multithreading concurrency volatile java-memory-model

我正在观看来自java jpoint会议的视频。

我对来自Alexey Shipilev报告的幻灯片提出了疑问:

enter image description here

对不起幻灯片上的非英语。实际上作者说变量集不可能是

r1 = 1 (Y)
r2 = 0 (x)
r3 = 1 (x)
r4 = 0 (Y)

根据视频,他暗示这显然是。

根据JMM,有人可以澄清为什么这个值设定不可能吗?

P.S。

如果我理解Alexey符号正确,则尊重以下代码:

public class SequentialConsistency {
    static volatile int x;
    static volatile int y;

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                x = 1;
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                y = 1;
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("r1=" + x + ", r2=" + y);
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("r3=" + x + ", r4=" + y);
            }
        }).start();
    }
}

3 个答案:

答案 0 :(得分:2)

相信我理解。

让我们说我们有4个帖子。 t1-t4(根据图片从左到右)

t3 读取 y 然后 x ,我们看到结果

y=1
x=0

这意味着序列如下:

  1. t1 y
  2. t3 读取 y
  3. t3 读取 x
  4. t2 x
  5. 这是唯一可行的序列。

    让我们检查 t4 读数:

    x=1
    y=0
    

    根据t3的推理,这意味着

    t2 write发生在t1 write之前,但它与 t3 输出相矛盾,因此不可能

答案 1 :(得分:2)

您可以为此代码构建详尽的SC执行列表,并且不会实现SC执行产生(1,0,1,0)。

模型方面,很容易争论。同步顺序(SO)一致性表示同步读取应该在SO中看到最后一次同步写入。 SO-PO一致性表示SO应该与程序顺序一致。

这允许通过矛盾来描绘证明。假设存在产生(1,0,1,0)的执行。然后,在那些执行中,由于SO的一致性,所以看到零必须按此顺序:

(r2 = x):0 --so--> (x = 1)  [1]
(r4 = y):0 --so--> (y = 1)  [2]

...并且其他两个读取必须按此顺序进行写入以查看它们(由于SO一致性):

(x = 1) --so--> (r3 = x):1  [3]
(y = 1) --so--> (r1 = y):1  [4]

......而且,由于SO-PO的一致性:

(r1 = y):1 --po--> (r2 = x):0  [5]
(r3 = x):1 --po--> (r4 = y):0  [6]

这产生了奇怪的传递性SO,它是循环的:

(r2 = x):0 --so--> (r3 = x):1 --so--> (r4 = y):0 --so--> (r1 = y):1 --so--> (r2 = x):0
            [1,3]               [6]               [2,4]               [5]

请注意,对于上面执行中的任何一对动作A!= B,我们可以说(A --so--> B)(B --so--> A) - 这称为对称性。根据定义,SO是总顺序,总顺序是反对称,这里我们有对称的。我们已经陷入矛盾,因此不存在这样的执行。 Q.E.D。

答案 2 :(得分:0)

您可以用稍微简单的形式来考虑它(尽管您无法得到比Aleksey所说的更正确的东西)。 Java中的volatile提供了sequential consistency,这意味着操作以全局和原子顺序 like 完成。如果您写入字段(x = 1),则每个人都会看到该写入。根据您的示例,使其更正确,如果有一个ThreadA执行x = 1,则ThreadB(执行r2 = x)和ThreadC(即r3 = x),将读取x1。这就是顺序一致性的保证。

幻灯片显示,在SC(顺序一致)中执行:1, 0, 1, 0是不可能的。因为那意味着:

ThreadA wrote to x value of 1
ThreadB observed that value to be 1 (via r2 = x)
ThreadC observed that value to be 0 (via r3 = x)

但是在SC世界中,一旦发生写操作(并且我们知道发生这种情况是因为ThreadB已经观察到了),那么其他所有人都必须观察到它。这里不是这种情况:ThreadC看到x0。因此,这会破坏SC。

您必须回想起他的观点是-“我们可以用发布/获取来替换所有易失性吗?(毕竟便宜)。”答案是否定的,因为SC 禁止 1, 0, 1, 0,而release/acquire 允许