对于Java volatile的理解

一、什么是volatile

简单来说就是Java并发机制的一个关键字,可以协助我们进行并发编程,同时也是面试高频考点。作用于字段(属性),可以保证改变量的内存可见性。

二、什么是内存可见性

1.理解内存可见性的前提是理解JMM(Java的内存模型),如下图。
我们知道线程在JMM的管理下有自己独立的内存空间,叫做 工作内存 ,线程的工作内存相互隔离不会共享但可以通讯,与之相反的是主内存,对各个线程数据共享。
在这里我们可以思考一个问题,这两种内存有什么区别?
回忆Java内存模型,我们可以知道Java内存包括了Stack和Head。其实工作内存就是Stack,主内存是Head。
对于Java volatile的理解

2.线程的工作过程是怎样的?
①线程从主内存copy一份数据到工作内存;
②然后在线程内部处理完后;
③数据写在工作内存中;
④把工作内存中的数据更新到主内存中。

三、举个例子

x = x+1

1.把x=1copy到线程A的工作内存;
2.在线程A的工作内存处理运算;
3.数据处理完毕,线程A的工作内存中记录着x=2,但此时在主内存中仍为x=1
4.最后把线程A的工作内存记录的x=2更新到主内存,此时主内存中为x=2

四、补充一个知识点

Java对于赋值字面量的操作是原子性的,比如说:
int a = 100;,可以直接把100一次性赋值给a。
但是,int b = a; 并不是原子型的操作,因为这里面需要两个步骤,首先读取a的值,然后才把a的值赋给b。

五、问题的提出

从上面的例子,我们大概就知道了,在多线程的环境中,数据的操作如果没有某种保护措施,就有可能产生并发问题。
举个例子,同样是:
x = x+1
现在有A、B两个线程执行该代码,当A线程把x的值copy到工作内存,并且完成计算,但是没有把数据更新到主内存,此时在主内存中x=1,线程B开始工作,把x的值copy到B的工作内存…问题很显然了,此时线程B copy的值为x=1,最终结果x=2,而正确答案应该是x=3

六、回归什么是内存的可见性

有了以上知识的疏通,大概就能够理解什么是内存的可见性了,内存的可见性指的是 每次读取到的变量,一定是最新的数据 ,怎样来理解呢?
①线程处理完的数据及时更新到主存中;
②被其他线程处理着的数据禁止被读取;
而volatile正是Java提供的可以达到保持可见性的目的的关键字!

七、应用

可以查看java.util.concurrent包下的原子类。