首页 > 编程语言 > 详细

【JMM】java内存模型及volatile关键字底层

时间:2021-02-21 09:20:28      阅读:32      评论:0      收藏:0      [点我收藏+]

1.计算机的cpu模型

技术分享图片

 

 。

2.

技术分享图片

 

 3.JMM的模型类似于计算机CPU的模型

技术分享图片

 

 我们的每一个线程都会有一个 主内存的共享变量的一个副本。

4.第一个volatile例子

不加volatile

技术分享图片

 

 技术分享图片

 

 输出结果

技术分享图片

 

 结果表示 标志位以及变为true。但是还是没跳出thread1的循环。

 

加了volatile

技术分享图片

 

 技术分享图片

 

 volatile保证变量可见性。

 

5.JMM数据原子操作

技术分享图片

 

 技术分享图片

 

 

 

6.早期多核cpu解锁可见性问题

技术分享图片

 

 类似于串行化执行线程。在每个线程读数据时加锁,然后写回主内存时释放锁。

 

7.后期解决cpu可见性问题。

技术分享图片

 

 技术分享图片

 

 这里对于各个线程在主内存里读数据并不加锁,可以并发的读。

但是当有线程向总线store 新的值时,别的线程的cpu总线嗅探机制 可以感知到数据的变化,从而使其工作内存的数据副本失效。

这时候需要重新在主内存里面读数据。

 

8.volatile的汇编底层

技术分享图片

 

 技术分享图片

 

 这个line30就是将flag赋值为true的代码。 加了volatile后当赋值后马上回写到主内存里

 

9.volatile加锁解锁

技术分享图片

 

 相比于总线加锁的低性能。

使用volatile+MESI可以使锁的密度降低。

在对变量进行赋值之后,马上为其变量加锁,然后向总线store。

在主内存对其更改之后,解锁。

因为当store时 其他线程开始向主内存读数据,这时候还没写入主内存呢。存在时间差。

 

10.

技术分享图片

 

 

11.

技术分享图片

 

 

12。不保证原子性的例子

技术分享图片

 

 当线程1 2同时进行num++。都变成了1,但是要写入总线的时候 需要lock。

假设线程1加了lock 线程2就阻塞了。

线程1写入总线 和主内存后 线程2嗅探到num变化,于是将刚才线程2算好的1失效变为主内存中 线程1算好的1.

但是这时候线程2已经要算第2次++了,第一次++就被浪费掉。

 

13.有序性例子

技术分享图片

 

【JMM】java内存模型及volatile关键字底层

原文:https://www.cnblogs.com/cckong/p/14423972.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!