Java 了解JVM之前发生的情况并重新排序

Java 了解JVM之前发生的情况并重新排序,java,jvm,Java,Jvm,我正在阅读关于内存模型的JLS规范。 我不明白第一条规则: “#如果x和y是同一线程的操作,并且x在程序中位于y之前 顺序,然后是hb(x,y)。” 假设A和B是可以在多个线程之间共享的对象(类对象的实例): int i=A.getNum(); // ActionA int j=B.getNum(); // ActionB 三个问题: 根据上述规则,它是否意味着hb(ActionA,ActionB) 如果1的答案为真,这是否意味着根据“发生在之前”规则,在遵循JSR133内存模型的任何JV

我正在阅读关于内存模型的JLS规范。 我不明白第一条规则:

“#如果x和y是同一线程的操作,并且x在程序中位于y之前 顺序,然后是hb(x,y)。”

假设A和B是可以在多个线程之间共享的对象(类对象的实例):

int i=A.getNum();  // ActionA
int j=B.getNum();  // ActionB
三个问题:

  • 根据上述规则,它是否意味着hb(ActionA,ActionB)

  • 如果1的答案为真,这是否意味着根据“发生在之前”规则,在遵循JSR133内存模型的任何JVM中,ActionB不能重新排序到ActionA之前

  • 如果1和2都是真的,那么ActionA和ActionB似乎不相关,为什么不能重新排序呢?就为了这个规格


  • 我的理解是:

  • 你说得对
  • 它们可以重新排序,但前提是动作B不依赖于动作A的结果
  • 发生在关系没有说明任何关于重新排序操作之前。它只是说,如果HB(A,B)成立,那么动作B必须看到动作A的记忆效应


    如果操作B没有使用操作A的任何结果,那么没有理由不能对其重新排序。(一般来说,“使用另一个操作的任何结果”是相当广泛的,并且只能在非常简单的操作(如内存读/写)中检测到,而不能在使用外部资源(如I/O操作或基于时间的操作)的操作中检测到)

    您的理解基本正确。但是,要记住的关键是:

    • 如果重新排序不影响其运行的线程的结果,则允许重新排序
    • 这并不意味着如果重新排序会影响其他线程,则不允许重新排序

    最后一个事实是java多线程编程中常见的错误和困惑

    是的,动作A发生在动作B之前。不过,请进一步阅读该部分。这并不一定意味着JVM不能对这些进行重新排序。这意味着ActionB必须观察ActionA的效果,仅此而已。如果ActionB从不依赖ActionA的效果,那就非常正确