Java线程内存模型

Java线程内存模型

1.多核并发缓存架构

中央处理器(CPU,central processing unit)
早期的计算机的cpu在计算时会直接与主内存打交道,因为主内存的效率太慢,所以在cpu与主内存之间加了cpu高速缓存。
在这里插入图片描述
2.JMM内存模型(JavaMemoryMode)
在这里插入图片描述
用下面的代码来证明每个线程都有自己的工作内存,如下图代码的运行结果:
在这里插入图片描述
在这里插入图片描述
运行效果如下:
在这里插入图片描述
为了使得线程都能够共享initFlag变量的值,我们在定义initFlag变量时加上volatile关键字,如下图:
在这里插入图片描述
运行结果如下:
在这里插入图片描述
问:volatile的作用?
答:内存可见性(Memory Visibility):所有线程都能看到共享内存的最新状态。
3.JMM数据原子操作
在这里插入图片描述
结合上述代码,volatile的底层机制原理分析如下:
线程1先从主内存中读取initFlag=false的值,进入死循环。线程2读取initFlag=false并修改为true并同步回主内存,但是该变量没有加volatile关键字,所以线程2修改了initFlag=true但是线程1没办法感知到,因此线程1会一直进入死循环。
在这里插入图片描述
问:如何解决JMM缓存不一致的问题?
答:方式一:早期采用的是总线加锁机制,当有一个cpu过来读取主内存的值时,总线会对该变量进行lock,此时则所有的cpu就会处于等待机制,直到那个cpu修改完变量值并同步给主内存后,总线才会unlock(释放锁),因此性能太低。因此采用MESI缓存一致性协议,会在read之前先lock。
在这里插入图片描述
方式二:加上volatile关键字后,其他的cpu就会开启MESI缓存一致性协议,开启总线嗅探机制来监听总线,因为线程2修改了initFlag的值在store的过程中会经过总线,那么线程1监听到initFlag的值已经修改,就会将自己工作内存中的initFlag值的状态置为失效,此时就会重新去主内存读取initFlag的值。volatile会在该cpu同步回主内存之前进行lock操作,直到同步完成后再unlock。如下图:
在这里插入图片描述
4.volatile底层原理分析
在这里插入图片描述
加了volatile关键字后,将代码使用汇编语言编译后,即使用的是lock的前缀指令,如上图,(1)会立即写回系统内存(主内存)的时候,会触发其他cpu的MESI协议和嗅探机制,则其他CPU就会将自己工作内存中的initFlag值的状态置为失效,此时就会重新去主内存读取initFlag的值。

5.并发编程volatile的可见性、原子性和有序性
在这里插入图片描述
synchronized可以保证原子性。如下图:volatile没办法保证原子性,工作内存中数据会失效。
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值