如何使用多个易失性字段使它们达到同步顺序?

问题描述 投票:0回答:1

以下JCStress测试的描述:

    @JCStressTest
    @Outcome(id = {"0, 1", "1, 0", "1, 1"}, expect = ACCEPTABLE, desc = "Trivial under sequential consistency")
    @Outcome(id = "0, 0",                   expect = FORBIDDEN,  desc = "Violates sequential consistency")
    @State
    public static class VolatileDekker {
        volatile int x;
        volatile int y;

        @Actor
        public void actor1(II_Result r) {
            x = 1;
            r.r1 = y;
        }

        @Actor
        public void actor2(II_Result r) {
            y = 1;
            r.r2 = x;
        }
    }

说:

向 $x 和 $y 添加 volatile 将它们组合在一起 同步顺序,因而要求结果一致 当读/写形成全序时的情况。

解释为什么结果

"0,0"
是不可能的。然而,
x
y
被放在一起成为同步顺序的原因是什么?引用《Java并发实践》

当线程A写入一个易失性变量并且随后 线程 B 读取同一个变量,即所有变量的值 在写入 volatile 变量之前对 A 可见,之后对 B 可见 读取易失性变量。

关于发生之前的关系,我假设编译器:

  • 无法对写入易失性字段之前的指令重新排序
  • 无法对读取之前的易失性字段之后的指令重新排序

使编译器能够:

  • 可能会对写入易失性字段之后的指令重新排序
  • 可能会对读取之前的易失性字段中的指令重新排序

因此产生以下代码:

        @Actor
        public void actor1(II_Result r) {
            r.r1 = y;
            x = 1;
        }

        @Actor
        public void actor2(II_Result r) {
            r.r2 = x;
            y = 1;
        }

可以得到

0,0
的结果,但似乎不可能。

java concurrency jcstress
1个回答
0
投票

你是对的。理论上是有可能得到

(0,0)
结果的。测试不会失败,因为实现没有进行重新排序,但根据规范这是可能的。

© www.soinside.com 2019 - 2024. All rights reserved.