java编程,如何彻底理解volatile关键字?


volatile在Java语言中扮演者重要的角色 。它具有可见性以及禁止指令重排序两个非常显著的特点 。要想解释清楚volatile的用法 。首先我们要对Java的内存模型JMM有一个非常熟悉的了解 。所以我从以下几点来分析volatile 。
一、Java内存模型JMM
Java的内存模型规定:所有的变量都保存在主内存中 。每一个线程都有属于自己的工作内存 。当读取主内存的变量时 。线程的工作内存都会都会存储这个变量的副本 。线程对变量的操作都是在自己的工作内存中 。在适当的时候会把自己工作内存的变量同步到主内存中 。
从上面的内容中可以得出一个结论 。多线程对变量的修改 。都是先修改自己的工作内存的变量 。然后把工作内存中修改的在适当的时候同步到主内存中 。那么问题就来了 。适当的时候是什么时候呢?不确定 。所以就有问题了 。当主内存中有一个变量i=0,假如同时有两个线程去修改i的值 。当线程1读取主内存中的i=1,然后拷贝一份副本在自己的工作内存中 。然后i=1,但是这是操作的自己的工作内存i=1,但是这个i=1什么时候刷新到主内存中呢?刚才我们说了 。不确定 。此时线程二读取主存的变量i=0,然后也拷贝一份到自己的工作内存中 。然后i=2,然后在适当的时候刷新到主存中 。所以最终的结果可能是线程二i=2的结果先刷新到主存中 。线程一i=1最后刷新到主存中 。这就导致现在主存中i=1,所以与想象的结果不一样 。

java编程,如何彻底理解volatile关键字?

文章插图
二、volatile的大白话
了解了Java的内存模型JMM 。我们了解了对于一个共享变量 。如果有多个线程并发的修改这个共享变量 。最终得到的结果可能与我们想象的不太一样 。这是由于JMM的机制导致的 。而这和我们所说的volatile有什么关系的 。那接下来我们就说说 。
结论:1:如果一个变量被volatile修饰 。那么它在工作内存中修改的变量会立刻被刷新到主存中 。而不是上面所说的不确定的时候
2:如果读取一个被volatile修饰的变量 。会把此线程工作内存中的此变量副本置为无效 。它会从主内存中重新读取这个变量到自己的工作内存 。
上面这两点分别是volatile写内存语义和volatile内存语义 。
java编程,如何彻底理解volatile关键字?

文章插图
三、volatile在JDK的使用
在JDK中 。并发包中volatile把它的特点发挥到了极致 。尤其通过框架AQS的state就是被volatile修饰的 。在加上CAS构建出了无锁化的同步框架 。在ConcurrentHashMap中也是因为有了volatile的作用加上CAS操作提高了很大的性能 。
java编程,如何彻底理解volatile关键字?

文章插图
上面3点只是简单的说明了volatile的作用 。如果要详细介绍volatile 。估计能够一本上百页的书了 。在这里就不再详述了 。如果想进一步了解volatile 。请关注我的头条 。我会有一个关于volatile的专题 。
其他观点:
谢谢邀请~!下面从 用法、注意事项、底层原理进行说明!
JMM 基础-计算机原理
Java 内存模型即Java Memory Model,简称JMM,JMM定义了Java 虚拟机(JVM)在计算机(RAM) 中的工作方式 。JVM 是整个计算机虚拟模型 。所以JMM是隶属于JVM的 。
java编程,如何彻底理解volatile关键字?

文章插图
java编程,如何彻底理解volatile关键字?

文章插图
在计算机系统中 。寄存器是L0级缓存 。接着依次是L1,L2,L3(接下来是内存 。本地磁盘 。远程存储).越往上的缓存存储空间越小 。速度越快 。成本也越高 。越往下的存储空间越大 。速度更慢 。成本也越低 。
从上至下 。每一层都都可以是看作是更下一层的缓存 。即:L0寄存器是L1一级缓存的缓存 。
L1是L2的缓存 。一次类推;每一层的数据都是来至于它的下一层 。
在现在CPU上 。一般来说L0,L1,L2 。L3都继承在CPU内部 。而L1还分为一级数据缓存和一级指令缓存 。分别用于存放数据和执行数据的指令解码 。每个核心拥有独立的运算处理单元、控制器、寄存器、L1缓存、L2 缓存 。然后一个CPU的多个核心共享最后一层CPU缓存L3 。
CPU 的缓存一致性解决方案
分为以下两种方案
总线锁(每次锁总线 。是悲观锁)
缓存锁(只锁缓存的数据)
java编程,如何彻底理解volatile关键字?

文章插图
java编程,如何彻底理解volatile关键字?

文章插图
MESI协议如下:

推荐阅读