volatile关键字
面试中常常会问道,说说你对volatile的理解?
上图中每个线程都有自己的工作内存,还有一个共享的主内存。当这两个线程需要读取变量data的值的时候,他们需要先从主内存将data变量的值加载到自己的工作内存,才可以使用这个值。
这个工作内存类似于一个高速的本地缓存,线程在代码的执行过程中,可以直接从自己本地缓存里加载变量副本,不需要要从主内存加载变量值,性能会得到极大的提升。
我们来设想一下,如果线程1修改了变量data的值为1并更新到工作内存,此时,主内存中的data值仍为0,线程2的工作内存中的data值也为0,此时线程1运行过程中读取到的data值为1,线程2运行时读取到的data值为0。
可以看出线程1和线程2都是在操作变量data,但是线程1修改了data的值之后,线程2是看不到的,它只能看到自己工作内存中的那个副本值,这个就是Java并发过程中的可见性问题。
这时候只要给变量data定义时增加一个volatile ,就可以解决多个线程之间变量可见性的问题。
变量data定义时用volatile修饰之后,线程1在修改data的值为1的时候,在修改完自己的工作内存中的值之后,会强制将这个值刷新到主内存,这样可以立即让主内存中的值立即变为最新值。
同时会强制其他线程的工作内存中的data变量直接失效过期,不允许再来读取和使用。这时候线程2需要用到data的值时会重新从主内存拉取数据到工作内存,就会把工作内存中的data值变为最新值。所以说volatile这个关键字完美的解决了线程之间可见性的问题。
我们来梳理一下:对一个变量增加volatile修饰,只要有线程修改这个变量的值,会立马强制刷新主内存更新为最新值。接着强制其他线程的本地内存中变量的数据缓存,其他线程在读取变量的时候就会重新从主内存加载数据。这就是volatile的工作原理,一个线程修改数据,其他线程立马可以看见。