本文翻译自http://tutorials.jenkov.com/java-concurrency/volatile.html (Jakob Jenkov)
Java volatile 关键字用于标记为一个存储于主存("being stored in main memory")的Java变量,更加准确的说,被定义为volatile变量将从主存中读取。而不是从CPU Cache中读取。并且volatile变量的写入也同样的写入到主存中。而不是CPU Cache。
事实上,Java5.0以后的volatile关键字保证volatile变量从主存中读写。
Java volatile 关键字保证了通过线程改变变量的值后的可见性。在一个多线程程序中当线程操作在 非volatile(non-volatile)变量上时,为了性能上的考虑。如果你的电脑包含多个CPU,每个线程将运行在不同的CPU上,这意味着每个线程将COPY变量到对应的CPU Cache中。问题的根源就在这里。
内存模型
使用非volatile变量不能够保证JAVA 虚拟机(JVM)从主存中读取数据到CPU Cache中,或者从CPU Cache中读取数据写入到主存中。这会导致很多问题。
想下一个场景,多个线程进入一个共享对象(shared object)这个对象包含一个counter变量。
public class SharedObject {再想想,仅仅只有一个线程1 增加counter变量的值。但是线程1和线程2不断读取counter的值。如果counter变量没有被定义为volatile ,程序不能保证couter变量的值从Cpu Cache写入到主存中。这意味着。counter变量在CPU Cache中的值将和主存中的值不同。
public int counter = 0;
}
线程的问题在于不能够感知到这个变量最新的值,因为他没有被另外一个线程写入到主存中。这是一个可见性的问题。一个线程对于另外一个线程是不可见的。
通过声明counter变量为volatile,所有修改counter变量的值将被马上回写到主存。并且所有couter变量的值将从主存中直接获得。下面是用volatile定义一个变量的形式。
public class SharedObject {定义一个volatile变量 因此能够保证所有对这个变量的修改对所有线程可见。
public volatile int counter = 0;
}