前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么是happens-before原则?

什么是happens-before原则?

作者头像
终有救赎
发布2023-10-16 10:25:10
1650
发布2023-10-16 10:25:10
举报
文章被收录于专栏:多线程

前言

本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见100个问题搞定Java虚拟机

正文

happens-before 关系是用来描述两个操作的内存可见性的。如果操作 X happens-before 操作 Y,那么 X 的结果对于 Y 可见。 Java 内存模型底层是通过内存屏障(memory barrier)来禁止重排序的。

线程内的happens-before

在同一个线程中,字节码的先后顺序(program order)也暗含了 happens-before 关系:在程序控制流路径中靠前的字节码 happens-before 靠后的字节码。

然而,这并不意味着前者一定在后者之前执行。实际上,如果后者没有观测前者的运行结果,即后者没有数据依赖于前者,那么它们可能会被重排序。

线程间的 happens-before

  1. 解锁操作 happens-before 之后(这里指时钟顺序先后)对同一把锁的加锁操作。
  2. volatile 字段的写操作 happens-before 之后(这里指时钟顺序先后)对同一字段的读操作。
  3. 线程的启动操作(即 Thread.starts()) happens-before 该线程的第一个操作。
  4. 线程的最后一个操作 happens-before 它的终止事件(即其他线程通过 Thread.isAlive() 或 Thread.join() 判断该线程是否中止)。
  5. 线程对其他线程的中断操作 happens-before 被中断线程所收到的中断事件 (即被中断线程的 InterruptedException 异常,或者第三个线程针对被中断线程的 Thread.interrupted 或者 Thread.isInterrupted 调用)。
  6. 构造器中的最后一个操作 happens-before 析构器的第一个操作。

happens-before关系的传递性

如果操作 X happens-before 操作 Y,而操作 Y happens-before 操作 Z,那么操作 X happens-before 操作 Z。

内存屏障(memory barrier)

对于即时编译器来说,它会针对前面提到的每一个 happens-before 关系,向正在编译的目标方法中插入相应的读读、读写、写读以及写写内存屏障。

这些内存屏障会限制即时编译器的重排序操作。

即时编译器将根据具体的底层体系架构,将这些内存屏障替换成具体的 CPU 指令。

以我们日常接触的 X86_64 架构来说,读读、读写以及写写内存屏障是空操作(no-op),只有写读内存屏障会被替换成具体指令。

对于即时编译器来说,内存屏障将限制它所能做的重排序优化。对于处理器来说,内存屏障会导致缓存的刷新操作。

volatile 字段禁止指令重排序的底层原理

以 volatile 字段访问为例,所插入的内存屏障将不允许 volatile 字段写操作之前的内存访问被重排序至其之后;

也将不允许 volatile 字段读操作之后的内存访问被重排序至其之前。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文
    • 线程内的happens-before
      • 线程间的 happens-before
        • happens-before关系的传递性
          • 内存屏障(memory barrier)
            • volatile 字段禁止指令重排序的底层原理
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档