volatile关键字的含义

来源:互联网 发布:《幻》知乎 编辑:程序博客网 时间:2024/05/16 04:56

背景:Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了同步块和volatile关键字机制。

Java内存模型

Java内存模型规定了所有的变量都存储在主存中,每条线程中有自己的工作内存,线程中的工作内存中保存了该线程所使用的变量(这些变量是从主存中拷贝而来)

线程对变量的所有操作都必须在工作内存中进行。不同线程之间无法直接访问对方工作内存中变量,线程变量值的传递均需要通过主内存来完成。


如图:Java内存模型:












Java并发编程三点要求:
  1. 原子性
  2. 有序性
  3. 可见性
一.原子性  

二.有序性
定义:即程序执行随着代码顺序而执行。

但是在程序执行的时候,为了提高执行效率,虚拟机会进行指令重排序已追求更高效率。重排序对单线程没有影响,也不会影响最终的结果,但其对多线程环境下的结果可能会产生影响,所以为了确保最终结果的正确性,我们就需要禁止重排序。
解决办法:JVM中对Java代码有个happened-before原则和使用volatile关键字确保了不会进行指令重排序继而保证有序性。

三.可见性
定义:当多个线程去访问同一个变量时,某个线程对变量执行修改后,其余线程会立刻看到修改的变量。
概述:

例如:

线程1执行的代码:

Int i=0;

I=10;

 

线程2执行的代码:

J=i;

 

结果为:J=0

 

解决:当一个共享变量被volatile修饰时,他会保证修改的值立即被更新到主存,当有其他线程需要读取时,他会去主存中读取新值。

另外还可以通过synchronizedlock能保证同一时刻只用一个线程获取锁然后执行同步代码,并且在释放锁之前会对变量的修改刷新到主存中,因此可以保证可见性。



总结;
volatile可以保证线程可见性且提供了一定的有序性,但是无法保证原子性。在jvm底层volatile是采用“内存屏障”来实现的。

一旦一个共享变量(类的成员变量,类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

保证了不同线程对这个变量进行操作时的可见性。

禁止进行指令重排序-----保证了有序性

注意:volatile不能保证原子性。













原创粉丝点击