Java内存模型,happen-before规则,JMM,volatile,有序性,可见性,原子性

Java内存模型

Java线程之间的通信由Java内存模型(本文简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。

从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。

Java内存模型的抽象示意图如下:

从上图来看,线程A和线程B之间进行通信必须经历两个步骤:

1、线程A把本地内存的共享变量刷新到主内存,

2、线程B通过读取主内存中之前线程A更新的变量。

下面通过示意图来说明这两个步骤:

如上图所示,线程A和B有主内存共享变量x的副本。假设一开始三个内存中的x=0,此时线程A需要与线程B通信。

线程A在执行时,将本地内存的变量x改为1,然后刷新到主内存中,主内存x=1;

此时线程B通过去主内存中读取之前线程A刷新的变量x=1,线程B的本地内存变量x也变为1。

从整体来看,这两个步骤实质上是线程A在向线程B发送消息,而且这个通信过程必须要经过主内存。

JMM通过控制主内存与每个线程的本地内存之间的交互,来为java程序提供内存可见性保证。

 

JMM 保证线程安全是围绕原子性、可见性、有序性这 3 个特性来建立的。

体贴的 JMM 在满足这 3 个特性的时候给了很多关键字或预定规则,比方说,在原子性中的 8 种操作,这样我们在操作基本数据类型的读和写就可以看成是线程安全的。

其中的 lock 和 unlock 指令在 Java 语言中的体现就是 synchronized 关键字,所以 synchronized 块之间的操作也是原子性的。

可见性的体现,volatile 关键字,上面已经说过了,还有两个关键字 synchronized 和 final。

因为被 synchronized 包围的代码被线程执行的前提是要 lock,对应的有条规则说到“对一个变量执行 unlock 之前,要先把其写回主存”。

而 final 定义的变量,一旦初始化完成,其它线程都能看到(当然这里假设不出现对象逃逸,就是不会在对象初始化没有完成的时候被其它线程拿到 this 对象进行操作。)

最后一个有序性,提供了关键字 volatile 和 synchronized,volatile 禁止重排序来达到有序,而 synchronized 则是基于 “一个变量在同一时刻只允许一条线程对其进行 lock 操作,lock 和 unlock 必须成对出现” 这个规则。

另外,JMM 为了保证有序,还内置了一套先行发生规则(happens-before)两个操作间具有 happens-before 关系,并不意味着前一个操作必须要在后一个操作之前执行。happens-before 仅仅要求前一个操作对后一个操作可见,和一般意义上时间的先后是不一样的,达到逻辑上的顺序执行即可。

如果 A 线程的写操作 a 与 B 线程的读操作 b 之间存在 happens-before 关系,尽管 a 操作和 b 操作在不同的线程中执行,但 JMM 向程序员保证 a 操作将对 b 操作可见。我们实际只想知道某线程的操作对另一个线程是否可见,于是就规定了 happens-before 这个可见性原则,程序员可以基于这个原则进行可见性的判断。

具体的规则如下:

1、程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生与书写在后面的操作。【保证单线程的有序】
2、锁定规则:一个 unlock 操作先行发生于后面对同一个锁的 lock 操作。
3、volatile 变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作。【先写后读】
4、传递规则:A 先于 B 且 B 先于 C 则 A 先于 C
5、线程启动规则:Thread 对象的 start 方法先行发生于此线程的每一个动作。
6、线程中断规则:对线程 interrupt 方法的调用先行发生于被中断线程的代码检测到中断事件的发生。【先中断,后检测】
7、线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过 Thread.join() 方法结束,Thread.isAlive() 的返回值手段检测线程已经终止执行。
8、对象终结规则:一个对象的初始化完成先行发生于它的 finalize 方法的开始。

如果两个操作的执行顺序不能通过 happens-before 原则推导出来,就不能保证他们的执行次序,虚拟机就可以随意的对他们进行重排序。

 

 更多内容关注公众号>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>2021最新面试题

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_夜半钟声到客船

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

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

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

打赏作者

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

抵扣说明:

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

余额充值