Java面试问题之 volatile 关键字到底是什么?
上周出去面试的小伙伴,被问到⼀个问题:说说你对 volatile 的理解?
因为他之前并没关注这个知识点,网上找了一下,发现还是不清楚,于是回来问我。
其实,还是有很多小伙伴都知道 volatile 是帮助可以解决线程安全问题的:
在 java 并发编程中,多个线程并发读写⼀个共享变量的时候,对其他线程不可见的,所以某个线程修改了变量的值,但是其他线程看不到的,不知道你已经修改了。
那如果要解决这个问题怎么办呢?
这时就轮到 volatile 闪亮登场了!你只要给 data 这个变量在 定义的时候加⼀个 volatile,就直接可以完美的解决这个可见性的问题。
比如下面的这样的代码,在加了 volatile 之后,会有啥作用呢?
第一步都是一样的,不管是否添加volatile 关键字,两个线程读取到主内存中的data到自己的工作内存。
因为 data 变量定义的时候加了 volatile 来修饰的话,那么线程 A 只要修改 data 变量 的值,就会在修改完自己本地工作内存的 data 变量值之后,强制将这个 data 变量最新的值刷回主内存
主内存里的 data 变量值立马更新变成最新的值!
如果此时,其他线程的工作内存中也有这个 data 变量的副本的话,那么会强制让其失效过期,不允许再次读取和使用了!
线程B 在代码运行过程中当再次读取 data 变量时,发现其已经过期了!!他就会重新从主内存中加载 data 最新的值!
整个过程,参见下图:
好啦,volatile 完美解决了 java 并发中可见性的问题!
总结
我们知道了:
对⼀个变量加了 volatile 关键字修饰之后,只要⼀个线程修改了这个变量的值,立马强制刷回主内存。接着强制过期其他线程的本地工作内存中的缓存,最后其他线程读取变量值的时候,强制重新从主内存来加载最新的值!
这样就保证,任何⼀个线程修改了变量值,其他线程立马就可以看见了!这就是所谓的 volatile 保证了可见性的工作原理!
另外需要注意的是:
但是 volatile 主要作用是保证可见性以及有序性, volatile 是不能保证原⼦性的!!!
如果是多个线程同时修改⼀个变量的值,那还是可能出现多线程并发的安全问题,导致数据值修改错乱,volatile 是不负责解决这个问题的,也就是不负责解决原子性问题!
原子性问题,得依赖 synchronized、ReentrantLock 等加锁机制来解决。