Java内存模型中线程发散操作和外部操作的示例

Java内存模型中线程发散操作和外部操作的示例,java,multithreading,java-native-interface,native,java-memory-model,Java,Multithreading,Java Native Interface,Native,Java Memory Model,我目前正在学习Java内存模型,我学习了不同类型的内存 其中有两个我并不完全理解: 外部行动和 线程发散动作 请解释这两种动作类型,并举例说明它们以及它们关于编译器重新排序和发生在关系之前的特殊属性。哦,本地调用也是外部操作吗 我认为,如果线程发散操作没有什么特别之处,它们就不会定义线程发散操作。那么,是什么让它们变得特别,以至于它们需要被定义为一种特殊的行为呢 如果我理解正确,外部操作是Java VM进程之外可见的东西,例如显示窗口、写入文件或连接到套接字 线程发散操作必须进入无限,而(t

我目前正在学习Java内存模型,我学习了不同类型的内存

其中有两个我并不完全理解:

  • 外部行动和
  • 线程发散动作
请解释这两种动作类型,并举例说明它们以及它们关于编译器重新排序发生在关系之前的特殊属性。哦,本地调用也是外部操作吗


我认为,如果线程发散操作没有什么特别之处,它们就不会定义线程发散操作。那么,是什么让它们变得特别,以至于它们需要被定义为一种特殊的行为呢

如果我理解正确,外部操作是Java VM进程之外可见的东西,例如显示窗口、写入文件或连接到套接字


线程发散操作必须进入无限
,而(true)
循环。

现有答案已经正确定义了这些操作

关于重新排序:请看以下线程发散操作的示例:

你会期望这个断言永远不会失败。如果没有线程发散操作,这是无法保证的,因为设置
foo=42
的不可访问定义可能会被重新排序以首先执行。这是JMM禁止的

类似地,增加外部行动以避免意外结果:

class Externalization { 

  int foo = 0; 

  void method() { 
    jni(); // external action
    foo = 42; 
  } 

  native void jni(); /* { 
    assert foo == 0; 
  } */ 
}

假设JNI方法是为了运行相同的断言而实现的,您不会期望它失败。JIT编译器无法确定任何外部操作的结果,因此JMM也禁止此类重新排序。

它们关于编译器重新排序的特殊属性是什么?所有本机方法都是外部行为吗?或者问另一个问题,非本机方法如何可以是外部的?对我来说,唯一可能是非本机和外部的事情是不安全的。但我不确定它是否是非本地的……我认为如果它们没有什么特别之处,它们就不会声明分歧行为。那么是什么让它们变得特别呢?好吧,我现在只是在猜测,但我认为分歧动作的特别之处在于,一旦线程有了分歧动作,它就不再重要了。任何JVM都通过本机方法(即“外部动作”)与“外部世界”进行通信。此外,外部操作还有一个附加参数:该操作引发的异常或本机方法返回的结果。
class Externalization { 

  int foo = 0; 

  void method() { 
    jni(); // external action
    foo = 42; 
  } 

  native void jni(); /* { 
    assert foo == 0; 
  } */ 
}