前言

熟悉 Java 并发编程的都知道,JMM(Java 内存模型) 中的 happen-before(简称 hb)规则,该规则定义了 Java 多线程操作的有序性和可见性,防止了编译器重排序对程序结果的影响。按照官方的说法:

当一个变量被多个线程读取并且至少被一个线程写入时,如果读操作和写操作没有 HB 关系,则会产生数据竞争问题。 要想保证操作 B 的线程看到操作 A 的结果(无论 AB 是否在一个线程),那么在 AB 之间必须满足 HB 原则,如果没有,将有可能导致重排序。 当缺少 HB 关系时,就可能出现重排序问题。

因此JMM在设计时,定义了如下策略:

  1. 对于会改变程序执行结果的重排序,JMM要求编译器和处理器必须禁止这种重排序。
  2. 对于不会改变程序执行结果的重排序,JMM对编译器和处理器不做要求(JMM允许这种重排序)。

HB 有哪些规则?

这个大家都非常熟悉了应该,大部分书籍和文章都会介绍,这里稍微回顾一下:

  1. 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;
  2. 锁定规则:在监视器锁上的解锁操作必须在同一个监视器上的加锁操作之前执行。
  3. **volatile变量规则:**对一个变量的写操作先行发生于后面对这个变量的读操作;
  4. **传递规则:**如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;
  5. **线程启动规则:**Thread对象的start()方法先行发生于此线程的每一个动作;
  6. **线程中断规则:**对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;
  7. **线程终结规则:**线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;
  8. **对象终结规则:**一个对象的初始化完成先行发生于他的finalize()方法的开始;

其中,传递规则我加粗了,这个规则至关重要。如何熟练的使用传递规则是实现同步的关键

然后,再换个角度解释 HB:当一个操作 A HB 操作 B,那么,操作 A 对共享变量的操作结果对操作 B 都是可见的。

同时,如果 操作 B HB 操作 C,那么,操作 A 对共享变量的操作结果对操作 B 都是可见的。

而实现可见性的原理则是 cache protocol 和 memory barrier。通过缓存一致性协议和内存屏障实现可见性。

总结

虽然本文标题是通过 happen-before 实现对共享变量的同步操作,但主要目的还是更深刻的理解 happen-before,理解他的 happen-before 概念其实就是保证多线程环境中,上一个操作对下一个操作的有序性和操作结果的可见性。

同时,通过灵活的使用传递性规则,再对规则进行组合,就可以将两个线程进行同步 —— 实现指定的共享变量不使用原语也可以保证可见性。虽然这好像不是很易读,但也是一种尝试。

关注我的微信公众号
​​​​

Java内存模型中happen-before原则相关推荐

  1. 什么是Java内存模型中的happens-before

    Java内存模型JMM Java内存模型(即Java Memory Model , 简称JMM),本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序个各个变量(包括实 ...

  2. 深入探索JVM高效并发 — Java内存模型(四) 先行发生原则

    先行发生原则 Java语言中有一个"先行发生"(Happens-Before)的原则.这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的非常有用的手段. 依赖这个原则,我们 ...

  3. 【JAVA】Java 内存模型中的 happen-before

    前言 Java 语言在设计之初就引入了线程的概念,以充分利用现代处理器的计算能力,这既带来了强大.灵活的多线程机制,也带来了线程安全等令人混淆的问题,而 Java 内存模型(Java Memory M ...

  4. Java内存模型中的三个代

    http://developer.51cto.com/art/200909/153154.htm 本文介绍Java内存模型中的三个代:年轻代,终身代以及永久代.文中图示了各个代的默认排列.本文适用于J ...

  5. java内存模型之先行发生原则

    happen-before(先行发生)原则 一.导语 二.概念 三.八个规则 1.程序次序规则 2.管程锁定规则 3.volatile变量规则 4.线程启动规则 5.线程终止规则 6.线程中断规则 7 ...

  6. Java 内存 关系_发生在Java内存模型中的关系之前

    (1) What does it really mean by saying "ordered before"? Because even if action_a happens- ...

  7. Java内存模型与happens-before原则

    Java内存模型 Java内存模型不同于Jvm内存模型,Java内存模型(JMM)规定了JVM必须遵循一组最小保证,这组保证规定了对变量的写入操作在何时将于其他线程可见. 在Java虚拟机规范中试图定 ...

  8. java内存模型—先行发生原则

    Java语言中有一个"先行发生"(happens-before)的原则.这个原则非常重要,它是判断数据是否存在竞争,线程是否安全的主要依据,依赖这个原则,我们可以通过几条规则一揽子 ...

  9. java happen-before_java 内存模型中的happen-before 是什么?

    happen-before 关系,是Java内存模型中保证多线程可见性的机制,也是对早期语言规范中含糊的可见性概念的一个精确定义. 它的具体表现形式,包括但远不止测试我们直觉中的 synchroniz ...

  10. Java——聊聊JUC中的Java内存模型(JMM)

    文章目录: 1.CPU缓存模型 2.Java内存模型Java Memory Model 3.JMM规范下的三大特性 3.1 原子性 3.2 可见性 3.3 有序性 4.JMM规范下,多线程对变量的读写 ...

最新文章

  1. Python之Fabric
  2. centos 查找nginx_centos7 nginx安装/启动/进程状态/杀掉进程
  3. 注册注解BeanDefinition
  4. C语言入门(4)——常量、变量与赋值
  5. 飞鸽传书2011什么时候更新?
  6. leetcode —— 38. 外观数列
  7. mysql备份时过滤掉某些库 以及 去掉Warning: Using a password on the command line interface can be insecure.提示信息...
  8. ps3存档是php文件,PS3存档修改图文详细全教程
  9. LeetCode(181)——超过经理收入的员工(MySQL)
  10. 不融资,如何在大数据BI市场占据一席之地
  11. educoder MongoDB 实验——数据库优化
  12. 怎么在pyqt界面上添加新菜单栏选项_PyQt创建菜单栏、工具栏
  13. Restful API 的设计规范
  14. html连接有道词典api,调用网易有道词典api
  15. response.addheader详解
  16. 超百个区块链应用落地福州,BSN助力数字应用第一城蓬勃发展
  17. MySQL中添加新字段
  18. uniapp链接生成二维码
  19. hdu 5055(坑)
  20. Java程序员学Golang

热门文章

  1. JS格式化输出常用格式
  2. amos看拟合度在哪里看_Amos软件完结篇!模型无法拟合,拟合指标不佳如何解决?...
  3. char,varchar,nchar,nvarchar的区别
  4. 台式电脑怎么改计算机名,台式电脑局域网设置方法
  5. 在ubuntu16.04运行neural baby talk
  6. 为了自己的梦想而努力
  7. 论文笔记 ACL 2017|Exploiting Argument Information to Improve Event Detection via Supervised Attention
  8. SOC课程实验——PC程序计数器设计
  9. 基于安卓系统(android)记事本APP管理系统设计与实现
  10. OpenJudge - 红与黑(DFS)