参考文章:http://www.cnblogs.com/Mainz/p/3556430.html#
一、Volatile如何保证可见性
1.1可见性及volatile
Volatile在java中是一个神秘的关键字,官方对其定义:
TheJava programming language provides a second mechanism, volatile fields, that ismore convenient than locking for some purposes. A field may be declaredvolatile, in which case the Java Memory Model ensures that all threads see aconsistent value for the variable.
大概意思是说:如果一个变量加了volatile关键字,就会告诉编译器和内存模型:这个变量对所有线程是共享的、可见的,每次JVM都会读取最新写入的值并使其最新值在所有CPU可见。
1.2 Volatile是如何保证可见性的:
在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。要解决这个问题,只有把该变量声明为volatile,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。而volatile关键字就是提示JVM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。
1.3 JVM具体是怎么实现Volatile的:
举例:例如一个volatile变量要实现自增分为三步:1)读取变量值到local. 2)增加变量的值 3)把local的值写回,让其它线程可见。这3步的jvm指令如下:
最后一步是内存屏障,简单来说就是通过确保一些操作的执行顺序和影响一些数据的可见性来是得不论是哪个线程读取该数据都得到的是最新值。
二、Atomic如何保证原子性
2.1 什么是原子性
如果一段代码被认为是Atomic,则表示执行该段代码时是不会被中断的(即原子性)
1.硬件原理:电位有关
2.逻辑理解:
三、为什么volatile不能保证原子性
举例:很明显volatile变量自增分为三步,三步完成之后才是内存屏障。那么在前三步就是线程不安全的。而Atomic变量提供自增原子操作,实现自增不会被打断。