同步块中的读取障碍和写入障碍是什么

我正在研究同步和volatile变量如何在java中工作,我遇到了一个名为read and write barrier的概念。 任何人都可以帮助我理解这些术语的含义

(上面的答案非常完整),我只想用一个简单的方案来演示这个概念

Thread 1 Thread 2 | | | | | | | Everything Thread 1 | | wrote before here | | | | | _ _ _ _ _ _ _ _ _ _ | ( write barrier) (happens before) (read barrier) | | _ _ _ _ _ _ _ _ | | is guaranteed | | to be visible to | | Thread 2 | | | 

内存屏障是代码中的概念“线”,它阻止编译器进行某些优化,并可能向处理器插入特殊的“同步”命令。 通常,编译器可以查看特定方法,并查看某些指令可以在不改变代码含义的情况下移动。 例如,如果你有

 int x = 0, y = 0; x++; y++; 

如果编译器认为有一些好处,它可以改为输出代码

 y++; x++; 

但是,如果xy是某个类中的字段,以便可以从其他线程中看到它们,则另一个线程可能会在您的方法运行时修改这些值。

内存屏障迫使编译器重新检查特定变量的值(在Java中,那些是volatileAtomic*类),以防某些其他线程在方法运行时修改它们,并且它使编译器无法生成重新排序可能会意外更改计算结果。 在支持多核/处理器的系统上,编译器还会强制处理器检查以确保其他处理器或硬件设备在此期间未修改变量。 Java(从Java 5开始)有一套非常明确的规则,用于说明之前发生的事情 。

这个FAQ有一些有用的解释,这些解释是在Java Memory Model开发时编写的。 请注意,虽然内存屏障的概念是跨语言,但大多数语言没有像Java那样明确定义它们的规则。

当您输入同步的代码块时,您将传递“读取屏障”,当它退出时,您将通过“写屏障”。

Is用于引用volatile属性,并在Threads需要更新volatile属性的值时给出指示。 如果其他人通过了写屏障,他们应该在通过读屏障时更新它。

类似于从volatile属性读取使得线程通过读屏障并且写入volatile属性会使您通过写屏障,因此比同步块更精细。

读写障碍用于通过JVM在最低级别实现Java内存模型的语义。

然而,Java语言规范中没有这个术语,这只是出现在之前发生关系的原因。 特别是

  • 在对同一变量的后续读取之前发生对易失性变量的写入
  • 退出同步块发生在相同的同步块的后续条目之前

当程序中的两个操作之间存在一个before-before关系时,您可以保证这两个操作将按顺序一致的顺序执行(即好像只有一个线程并且没有不直观的重新排序)。

深入研究JVM的实现细节对于编写正确的multithreading程序是不必要的。 但是,如果你想要血淋淋的细节, JSR-133食谱是一个有趣的阅读。