为什么会有happens-before 规则?

因为jvm会对代码进行编译优化,指令会出现重排序的情况,为了避免编译优化对并发编程安全性的影响,需要happens-before规则定义一些禁止编译优化的场景,保证并发编程的正确性。

public class HappenBeforeTest {int a = 0 ;volatile boolean b = false;public void writer(){a = 42;b = true;}public void reader(){if (b == true){// 这里a会是多少呢System.out.println(a);}}
}

抛出问题:假设有两个线程A和B,A执行了writer方法,B执行reader方法,那么B线程中独到的变量x的值会是多少呢?

jdk1.5之前,线程B读到的变量a的值可能是0,也可能是42,jdk1.5之后,变量a的值就是42了。原因是jdk1.5中,对volatile的语义进行了增强。来看一下happens-before规则在这段代码中的体现。

happen-before的8大原则

  1. 单线程happen-before原则:在同一个线程中,书写在前面的操作happen-before后面的操作。
      首先是单线程的 HB ,前面的操作产生的结果必须对后面的操作可见。而不是前面的操作必须先于后面的操作执行,比如按照 as-if-serial 语义,没有数据依赖的两条指令是可以进行重排序的。而这种情况对于 HB 原则来说,因为两条指令都没有产生对方需要的结果,而不需要对对方可见,及时执行顺序被调转也是符合 HB 原则的。
      2. 锁的happen-before原则:同一个锁的unlock操作happen-before此锁的lock操作。
      个人理解强调的是解锁操作在多线程环境的可见性。一个线程进行了解锁操作,对于晚于该操作的加锁操作必须能够及时感应到锁的状态变化。解锁操作的结果对后面的加锁操作一定是可见的,无论两个是否在一个线程。
      3. volatile的happen-before原则: 对一个volatile变量的写操作happen-before对此变量的任意操作。
      对 volatile 变量的写操作的结果对于发生于其后的任何操作的结果都是可见的。x86 架构下volatile 通过内存屏障和缓存一致性协议实现了变量在多核心之间的一致性。
      4. happen-before的传递性原则: 如果A操作 happen-before B操作,B操作happen-before C操作,那么A操作happen-before C操作。
      HB 可以说是两项操作之间的偏序关系,满足偏序关系的各项性质,我们都知道偏序关系中有一条很重要的性质:传递性,所以Happens-Before也满足传递性。这个性质非常重要,通过这个性质可以推导出两个没有直接联系的操作之间存在Happens-Before关系
      5. 线程启动的happen-before原则:同一个线程的start方法happen-before此线程的其它方法。
      start 放法与其它方法可能并没有数据依赖关系,但是显而易见的,为了程序的正确性,我们必须做到这一点。start 方法造成的函数副作用必须对其它方法可见。
      6. 线程中断的happen-before原则:对线程interrupt方法的调用happen-before被中断线程的检测到中断发送的代码。
      interrupt 方法改变的状态必须对后续执行的检测方法可见。
      7. 线程终结的happen-before原则:线程中的所有操作都happen-before线程的终止检测。
      为了安全的关闭线程,线程中的方法造成的函数副作用必须对线程关闭方法可见。
      8. 对象创建的happen-before原则:一个对象的初始化完成先于他的finalize方法调用。
      单线程下对象的创建于销毁存在数据依赖,该条原则强调的是多线程情况下对象初始化的结果必须对发生于其后的对象销毁方法可见。

happen-before原则相关推荐

  1. 深入研究ConcurrentHashMap 源码从7到8的变迁

    ConcurrentHashMap是线程安全且高效的HashMap 1 为什么要使用ConcurrentHashMap 线程不安全的HashMap HashMap是Java中最常用的一个Map类,性能 ...

  2. 面试再被问到 ConcurrentHashMap,把这篇文章甩给他!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:^_TONY_^ cnblogs.com/ITtangtan ...

  3. 转:【Java并发编程】之十六:深入Java内存模型——happen-before规则及其对DCL的分析(含代码)...

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17348313 happen-before规则介绍 Java语言中有一个"先行发生 ...

  4. Java高并发编程(八):Java并发容器和框架

    1. ConcurrentHashMap 1.1 ConcurrentHashMap的优势 在并发编程中使用HashMap可能导致程序死循环.而使用线程安全的HashTable效率又非 常低下,基于以 ...

  5. ConcurrentHashMap之实现细节

    http://www.iteye.com/topic/344876 实现原理  锁分离 (Lock Stripping) ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁 ...

  6. Java并发容器(一) CocurrentHashMap的应用及实现

    转载自 http://blog.csdn.net/qq_24451605/article/details/51125946 CocurrentHashMap的优势 首先常用三种HashMap包括Has ...

  7. java中 d_Java 中的 syncronized 你真的用对了吗

    生活中随处可见并行的例子,并行 顾名思义就是一起进行的意思,同样的程序在某些时候也需要并行来提高效率,在上一篇文章中我们了解了 Java 语言对缓存导致的可见性问题.编译优化导致的顺序性问题的解决方法 ...

  8. 聊聊并发(四)深入分析ConcurrentHashMap

    转载自  聊聊并发(四)深入分析ConcurrentHashMap 术语定义 术语 英文 解释 哈希算法 hash algorithm 是一种将任意内容的输入转换成相同长度输出的加密方式,其输出被称为 ...

  9. 聊聊并发(四)——深入分析ConcurrentHashMap

    转载自:http://www.infoq.com/cn/articles/ConcurrentHashMap 术语定义 术语 英文 解释 哈希算法 hash algorithm 是一种将任意内容的输入 ...

  10. 并发容器与框架——并发容器(一)

    2019独角兽企业重金招聘Python工程师标准>>> Java中提供了非常多的并发容器和框架,在此仅对部分并发容器进行介绍. 1.ConcurrentHashMap的实现原理与使用 ...

最新文章

  1. 【BZOJ】3173: [Tjoi2013]最长上升子序列(树状数组)
  2. 没登录网页也能个性化推荐?一文详解浏览器指纹
  3. 将Win10包含中文的用户名改为英文的,解决Anaconda navigator无法运行jupyter的问题
  4. esp32 嵌入式linux,初体验乐鑫 ESP32 AT 指令-嵌入式系统-与非网
  5. 自定义DataAnnotations
  6. 【HDU5299】Circles Game,圆的扫描线+树上删边游戏
  7. 数据挖掘--分类思维导图
  8. 特斯拉线圈怎么用_中二科技_场管自激特斯拉线圈的制作
  9. (学习笔记)laravel 中间件
  10. 浅析 Spring 中的事件驱动机制
  11. 常微分方程之Kutta公式、Gill公式、隐式龙格库塔公式、半隐式龙格库塔公式、Milne方法、Hamming方法、不显含一阶导数的二阶微分方程的求解方法、非线性微分方程的差分法
  12. 天地图显示不全的问题
  13. cdr怎么把矩形去掉一个边_如何把一个矩形的四个角变形?
  14. 常用正则表达式大全 (转)
  15. 小心肝队-冲刺日志(第六天)
  16. 动漫推荐之恋爱随意链接
  17. python语言编程是什么意思_python中的“//”是什么意思
  18. Linux系统病毒防治
  19. Java高级:新特性:lambda 函数式接口 方法引用 StreamAPI Optional类
  20. SW2019SP0软件安装教程|兼容WIN10

热门文章

  1. java扫雷初级代码_运行在Eclipse环境下的java扫雷游戏的初级代码是什么?
  2. js中继承的方法总结(apply,call,prototype)
  3. 百位明星身份证照片被曝光
  4. 读优美博文了解低风险套利策略
  5. 微秒, 纳秒,毫秒, 时间单位换算[转]
  6. java渗透_java 渗透模型
  7. 十年磨一剑,今日把示君:架构师分享从一名码农到如今的成长经验
  8. 抄送列表 ,处理邮件,年会抽奖
  9. 论文阅读——Towards Adversarially Robust Object Detection
  10. golang 隐藏启动其他程序,包含cmd窗口(黑窗口)程序,GUI程序隐藏