【问题标题】:what are read barriers and write barriers in synchronized block什么是同步块中的读屏障和写屏障
【发布时间】:2013-08-31 09:39:02
【问题描述】:

我正在研究 java 中同步和 volatile 变量的工作方式,我遇到了一个名为 read and write barrier 的概念。谁能帮我理解这些术语的含义

【问题讨论】:

标签: java multithreading


【解决方案1】:

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

 Thread 1                                                             Thread 2


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

【讨论】:

    【解决方案2】:

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

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

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

    y++;
    x++;
    

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

    内存屏障强制编译器重新检查特定变量的值(在 Java 中,这些是 volatile 和 Atomic* 类),以防在方法运行时其他线程修改了它们,并且它可以防止编译器进行可能意外更改计算结果的重新排序。在支持多个内核/处理器的系统上,编译器还将强制处理器检查以确保其他一些处理器或硬件设备在此期间没有修改变量。 Java(从 Java 5 开始)有一套非常明确的规则来说明其工作方式,称为happens-before。

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

    【讨论】:

    • 最好的答案,但内存屏障不仅仅是一个编译器概念,也是一个硬件概念。处理器可以具有本地缓存​​,以防止它们看到在其他线程中进行的内存更新(在同一系统中的其他处理器上运行);某些处理器指令可用于刷新这些缓存或强制读取/写入语义。
    • 好点,我将进行编辑以反映这一点。 (最近在根本没有缓存的处理器上花费了太多时间......)
    【解决方案3】:

    当你进入一个同步的代码块时,你会通过“读屏障”,当它退出时,你会通过“写屏障”。

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

    从 volatile 属性中读取类似的内容会使您的线程通过读屏障,而写入 volatile 属性会使您通过写屏障,因此比同步块更细粒度。

    【讨论】:

      【解决方案4】:

      读写屏障被JVM用来在最底层实现Java内存模型的语义。

      但是,Java 语言规范中没有该术语,它仅根据 happens-before 关系进行解释。特别是

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

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

      为了编写一个正确的多线程程序,没有必要深入研究 JVM 的实现细节。但是,如果您想了解血淋淋的细节,JSR-133 cookbook 是一本有趣的书。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-18
        • 1970-01-01
        • 2015-03-09
        • 1970-01-01
        • 2021-12-02
        • 1970-01-01
        • 1970-01-01
        • 2017-10-19
        相关资源
        最近更新 更多