并发理论:Java如何解决可见性和有序列性

在这里插入图片描述

解决重排序引起的有序性

在之前的章节中,我们分析到基于执行效率的考虑,代码会被重排序
在这里插入图片描述
重排序会经历如下几个过程
在这里插入图片描述
当然重排序也不是随便排,需要遵循as-if-serial原则,即不管怎么重排序(单线程)程序的执行结果不能被改变。编译器,runtime和处理器都必须遵循as-if-serial语义

例如如下一段代码

double pi = 3.14 // a
double r = 1.0   // b
double area = pi * r * r  // c

数据之间的依赖关系如下所示
在这里插入图片描述
A和B之间并没有依赖关系,因此可以执行重排序
在这里插入图片描述
重排序除了需要遵循as-if-serial原则(用于单个线程),Java还定义了happens-before原则也需要遵循(用于单个线程和多个线程)

两个操作之间具有happens-before关系,并不意味着前一个操作必须妖在后一个操作之前执行!happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前

如下为java中定义的8种happens-before原则

  1. 一个线程中的每个操作happens-before于该线程中的任意后续操作
  2. 对一个锁的解锁,happens-before于随后对这个锁的加锁
  3. 对一个volatile域的写,happens-before于任意后续对这个volatile域的读
  4. 如果A hapens-before B,且B happens-before C, 那么A happens-before C
  5. 如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before 于线程B中的任意操作
  6. 如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before 于线程A从ThreadB.join()操作成功返回
  7. 对线程interrup()方法的调用, happens-before 于被中断线程的代码检测到中断事件的发生
  8. 一个对象的初始化完成(构造函数执行结束)happens-before finalize()方法的开始

解决缓存引起的可见性

在Java中无论是锁还是volatile等,都是通过内存屏障来实现可见性的。

在Java中有如下四种屏障类型

屏障类型指令示例说明
LoadLoad BarriersLoad1; LoadLoad; Load2确保Load1数据的装载先于Load2及所有后续装载指令的装载
StoreStore BarriersStore1; StoreStore; Store2确保Store1数据对其他处理器可见(刷新到内存)先于Store2及所有后续存储指令的存储
LoadStore BarriersLoad1; LoadStore; Store2确保Load1数据装载优先于Store2及所有后续的存储指令刷新到内存
StoreLoad BarriersStore1; StoreLoad; Load2确保Store1数据对其他处理器变得可见(只刷新到内存)先于Load2及所有后续装载指令的装载

在这里插入图片描述

内存屏障主要有如下两个作用

  1. 阻止屏障两侧的指令重排序
  2. 强制将内存中的数据写回主内存

对于Load Barrier来说,在指令前插入Load Barrier,可以让高速缓存中的数据失效,强制从新从主内存加载数据

对于Store Barrier来说,在指令后插入Store Barrier,能让写入缓存中的最新数据更新写入主内存,让其他线程可见

参考博客

[1]https://www.cnblogs.com/wenjieyatou/p/6210189.html
[2]https://www.jianshu.com/p/1508eedba54d/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Java识堂

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

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

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

打赏作者

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

抵扣说明:

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

余额充值