Happens-Before规则和内存屏障指令

        首先了解一下什么是JMM,JMM是Java内存模型,它规定和指引Java程序在不同的内存架构,CPU和操作系统间有确定性行为。它在多线程的情况下尤其重要。Java内存模型对一个线程所作的变动能被其他可见提供了保证,它们之间是先行发生关系。

         JSR-133内存模型规范使用Happens-before的概念来阐述操作之间的内存可见性。在JVM中如果一个操作执行的结果需要对另外一个操作可见,那么这两个操作之间必须要存在Happens-Before关系。Happens-Before规则:

  • 程序顺序规则:一个线程中的每个操作发生在该线程中的任意后续操作之前
  • 监视器锁规则:对一个监视器的解锁操作发生在随后的加锁操作之前
  • volatile变量规则:对一个volatile变量的写发生在后续任意对这个变量的读操作之前
  • 传递性规则:如果A happens-before于B,B happens-before于C,那么A happens-before于C
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作;
  • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;
  • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;
  • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始;
     

内存屏障指令:用于禁止特定类型的指令重排序,不让编译器优化

指令重排序的示例:

在DCL单例模式中会用volatile来修饰单例变量。singleton = new Singletion();这句话的执行顺序是:分配内存,初始化,对象指向内存空间。编译器优化,指令重排序后是:分配内存,对象指向内存空间,初始化。如果该instance中有成员变量,那么先指向内存空间再初始化会导致成员变量没有初始化,只是instance初始化了,也就是instance只部分初始化了,虽然拿不到多个实例,但是也拿不到整个实例。所以用volatile修饰后编译后的代码中会有lock前缀指令,lock前缀指令实际上相当于一个内存屏障,内存屏障会提供3个功能:1. 它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;2. 它会强制将对缓存的修改操作立即写入主存;  3. 如果是写操作,它会导致其他CPU中对应的缓存行无效。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卷福。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值