Loading

Volatile关键字原理

转载请标明:https://www.cnblogs.com/tangZH/p/15113505.html

一、如果一个变量被volatile关键字修饰,那么所有线程都是可见的。所谓可见就是,当一条线程修改了这个变量值,新值对于其他线程来时是立即可见的; 而普通变量不能做到这一点。

 

1、现在计算机缓存架构:

 

 CPU与内存之间存在缓存。

 

2、Java内存模型(JMM:java memory model)。

 

这里的主内存再java中相当于堆。

 

在不同线程中操作同一个变量,实际上操作的是各自工作内存中的一个副本。

 

3、JMM的8大原子操作:

 

 

 4、过程:

当线程1需要用到变量a的时候,会通过read操作将a读入临时区,然后再通过load操作载入到变量副本中。

需要用这个变量的话就用use操作。

 

当线程2需要用到这个变量的时候也是一样的过程。

如果变量没有加volatile,那么两个线程用到的变量实际上是不一样的。

 

 

加上volatile之后:

 

会强制将缓存刷新到主内.会激活总线嗅探器。当我们改变该变量在副本里面的值后写回主内存时,总线监听到就会去通知其余线程将该变量的副本移除,然后再改变主内存中的值。这样当其他线程再次用到该变量的时候就会重新从主内存里面拿了。

 

总线嗅探器机制也被叫做MESI缓存一致性协议。

 

二、Volatile能够禁止指令重排。

1、先看对象的生成过程,底层的指令如下:

 

 (1)、new 一个obj,此时内存里面的初始值为0.

 (2)、再栈里面生成一个引用。

 (3)、执行构造方法,将值改变。

 (4)、将引用指向内存。

而编译器会进行优化,编译器优化是指,在不改变原来语义的情况下,通过调整语句顺序,来让程序运行的更快。比如将(3)、(4)交换顺序不会有什么影响(单线程情况下)。

 

具体例子看:

单例模式的双重检测

 

posted @ 2024-03-03 13:52  妖久  阅读(12)  评论(0编辑  收藏  举报