浅谈java内存模型和volatile可见性实现原理

之前的文章写了volatile关键字特点及AtomicInteger类的实现,这篇文章分析一下volatile为什么能保证变量在多线程间的可见性。

volatile关键字的主要作用

  1. 保证变量在多线程间的可见性
  2. 禁止指令重排

JMM中变量操作的方式

java内存模型中,内存分主内存工作内存,每个线程创建都有自己的工作空间。为了提高处理器的执行速度,规定了所有的变量都存储在主内存中,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。所以,就可能出现线程1改了某个变量的值,但是线程2不可见的情况。

缓存一致性协议

一致性缓存:所有缓存副本中的值都相同,多个CPU处理器共享缓存并且更改共享数据时,更改必须广播到所有缓存副本。
在处理器中,嗅探是一致性缓存的常见的机制。工作原理是通过总线监听所有的共享数据的操作,当修改共享数据的事件发生时,所有监听处理器都会检查是否存在当前共享数据的副本,如果存在,监听处理器会执行刷新或者直接失效缓存副本操作。

基于上面对JMM和缓存一致协议的了解,volatile就是通过缓存一致性协议解决的JMM中不同线程对变量操作带来的不可见情况。

volatile变量在操作过程中可见性的实现

当线程A对volatile修饰的变量修改时,会把修改后的新值即时刷入主内存中,同时根据缓存一致性协议的实现,如MESI协议中CPU通过嗅探的方式把其他副本中对应的更改变量所在的的缓存行CacheLine或者缓存块置为失效状态或者更新为新值。当线程B读取被A修改的变量时,由于失效了就会重新读取主存中的值创建新的副本,这样就保证了变量被线程A修改后对线程B来说是可见的了。

猜你喜欢

转载自blog.csdn.net/qq_29569183/article/details/112778953
今日推荐