vlambda博客
学习文章列表

Java面试问题之 volatile 关键字到底是什么?

周出去面试的小伙伴,被问到⼀个问题:说说你对 volatile 的理解


因为他之前并没关注这个知识点,网上找了一下,发现还是不清楚,于是回来问我。

 

其实,还是有很多小伙伴都知道 volatile 是帮助可以解决线程安全问题的:

在 java 并发编程中,多个线程并发读写⼀个共享变量的时候,对其他线程不可见的,所以某个线程修改了变量的值,但是其他线程看不到的,不知道你已经修改了。

 

那如果要解决这个问题怎么办呢?

 

这时就轮到 volatile 闪亮登场了!你只要给 data 这个变量在 定义的时候加⼀个 volatile,就直接可以完美的解决这个可见性的问题。

比如下面的这样的代码,在加了 volatile 之后,会有啥作用呢?

 

  1. 第一步都是一样的,不管是否添加volatile 关键字,两个线程读取到主内存中的data到自己的工作内存。

     

  2. 因为 data 变量定义的时候加了 volatile 来修饰的话,那么线程 A 只要修改 data 变量 的值,就会在修改完自己本地工作内存的 data 变量值之后,强制将这个 data 变量最新的值刷回主内存

     

  3. 主内存里的 data 变量值立马更新变成最新的值!

     

  4. 如果此时,其他线程的工作内存中也有这个 data 变量的副本的话,那么会强制让其失效过期,不允许再次读取和使用了!

     

  5. 线程B 在代码运行过程中当再次读取 data 变量时,发现其已经过期了!!他就会重新从主内存中加载 data 最新的值!

     

整个过程,参见下图:

 

好啦,volatile 完美解决了 java 并发中可见性的问题!

 

总结

我们知道了:

对⼀个变量加了 volatile 关键字修饰之后,只要⼀个线程修改了这个变量的值,立马强制刷回主内存。接着强制过期其他线程的本地工作内存中的缓存,最后其他线程读取变量值的时候,强制重新从主内存来加载最新的值!

这样就保证,任何⼀个线程修改了变量值,其他线程立马就可以看见了!这就是所谓的 volatile 保证了可见性的工作原理!

 

另外需要注意的是:

但是 volatile 主要作用保证可见性以及有序性, volatile 是不能保证原⼦性的!!!

如果是多个线程同时修改⼀个变量的值,那还是可能出现多线程并发的安全问题,导致数据值修改错乱,volatile 是不负责解决这个问题的,也就是不负责解决原子性问题!

原子性问题,得依赖 synchronized、ReentrantLock 等加锁机制来解决。