java volatile关键字 使用说明以及JMM(java 内存模型)

 2019-12-10 15:54  阅读(884)
文章分类:Java Core

本文翻译自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中。问题的根源就在这里。

20191210001400\_1.png

内存模型

使用非volatile变量不能够保证JAVA 虚拟机(JVM)从主存中读取数据到CPU Cache中,或者从CPU Cache中读取数据写入到主存中。这会导致很多问题。

想下一个场景,多个线程进入一个共享对象(shared object)这个对象包含一个counter变量。

public class SharedObject {

        public int counter = 0;

    }

再想想,仅仅只有一个线程1 增加counter变量的值。但是线程1和线程2不断读取counter的值。如果counter变量没有被定义为volatile ,程序不能保证couter变量的值从Cpu Cache写入到主存中。这意味着。counter变量在CPU Cache中的值将和主存中的值不同。

20191210001400\_2.png

线程的问题在于不能够感知到这个变量最新的值,因为他没有被另外一个线程写入到主存中。这是一个可见性的问题。一个线程对于另外一个线程是不可见的。

通过声明counter变量为volatile,所有修改counter变量的值将被马上回写到主存。并且所有couter变量的值将从主存中直接获得。下面是用volatile定义一个变量的形式。

public class SharedObject {

        public volatile int counter = 0;

    }

定义一个volatile变量 因此能够保证所有对这个变量的修改对所有线程可见。

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> java volatile关键字 使用说明以及JMM(java 内存模型)

相关推荐