当前位置: 首页 > 知识库问答 >
问题:

顺序一致性易失性解释

贾兴学
2023-03-14

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

我对以下Alexey Shipilev报告幻灯片有疑问:

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

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

附注。

如果我理解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();
    }
}

共有1个答案

慕胡媚
2023-03-14

您可以为该代码构造完整的SC执行列表,并实现没有SC执行产生(1,0,1,0)。

从模型的角度来看,它很容易引起争论。同步顺序(Synchronization order,SO)一致性表示同步读取应该看到SO中的最后一个同步写入。SO-PO一致性表示SO应该与程序顺序一致。

这样就可以用矛盾来勾画证明。假设产生(1,0,1,0)的执行存在。然后,在这些执行中,读为see 0必须按照这样的顺序,由于如此一致:

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

...而另外两个读和写必须按照这样的顺序才能看到它们(由于如此一致):

(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]

这就产生了奇怪的传递性,所以是循环的:

(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]
 类似资料:
  • 问题内容: 如果高速缓存一致性是在硬件级别实现的,为什么我们需要可变的?任何内核/处理器都应该获得最新值吗? 还是完全解决了另一个问题? 问题答案: 高速缓存一致性可以在处理器级别实现,但是,除非处理器内存模型保证顺序一致性(在大多数现代体系结构中不是这种情况),否则只有在需要时才会获得高速缓存一致性。 这就是volatile的含义:它要求JVM生成相关的机器指令,这些指令将要求处理器将其缓存与主

  • 如果缓存一致性是在硬件级别实现的,为什么我们需要volatile?任何核心/处理器都应该获得最新的值? 还是它完全在处理一个不同的问题?

  • 在此处的oracle Java文档中,说明如下: 原子操作不能交错,因此可以在不担心线程干扰的情况下使用它们。然而,这并不能消除同步原子操作的所有需要,因为内存一致性错误仍然是可能的。使用易失性变量可以降低内存一致性错误的风险,因为对易失性变量的任何写入都会与该变量的后续读取建立“发生在之前”的关系。这意味着对易失性变量的更改对其他线程总是可见的。此外,这还意味着当线程读取volatile变量时,

  • 在阅读了这个问题和这个(尤其是第二个答案)之后,我对volatile及其关于记忆障碍的语义感到非常困惑。 在上面的例子中,我们写入一个易失性变量,这会导致一个mitch,这反过来会将所有挂起的存储缓冲区/加载缓冲区刷新到主缓存,使其他缓存行无效。 然而,非易失性字段可以优化并存储在寄存器中,例如?那么,我们如何才能确保给定一个写入易失性变量之前的所有状态变化都是可见的呢?如果我们有1000件东西呢

  • 我对下面的代码段有一个问题。结果可能有一个结果[0,1,0](这是用JCStress执行的测试)。那么这是怎么发生的呢?我认为数据写入(data=1)应该在Actor2(guard2=1)中写入到guard2之前执行。我说得对吗?我问,因为很多时候我读到挥发物周围的说明没有重新排序。此外,根据这一点:http://tutorials.jenkov.com/java-concurrency/vola

  • 我在网上找到两个定义: 顺序一致性——任何执行的结果都是相同的,就像所有处理器的操作都是按某种顺序执行的一样,每个处理器的操作按程序指定的顺序出现在这个顺序中。 最终一致性——如果没有对给定的数据项进行新的更新,最终对该项的所有访问都将返回最后更新的值。 定义对我来说很清楚。但是,当最终一致性不是顺序时,我没有得到。例如:mem 中的初始值为 0。水平轴是时间。 因此,有一些顺序,如果我们在 (x