关于Java中volatile关键字笔记

volatile通常被认为是一种轻量级的synchronized,字面上它表示易变的,在并发编程中,它保证了共享变量的可见性。所谓可见性指的是,某个线程对变量进行操作后,其他线程能够读取到操作后的最新结果。

CPU通常不会直接与内存通信,内存中的数据首先会被读取到缓存中进行读写。当对声明了volatile的变量进行写操作时,JVM会向处理器发送一条Lock前缀的指令,表示将变量锁在的缓存行数据写回内存中。

当写一个volatile变量时,Java内存模型JMM会把线程对应的本地内存的共享变量刷新到主内存中

 

然而volatile并不能保证线程安全,来看下面的例子

public class VolatileTest {
    private static volatile Integer num = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[10];
        for (int i = 0; i < 10; i++) {
            threads[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int k = 0; k < 10000; k++) {
                        num++;
                    }
                }
            });
            threads[i].start();
        }
        for (int i = 0; i < 10; i++) {
            threads[i].join();
        }
        System.out.println(num);
    }
}

 

这一段代码的期望运行结果应当是输出100000,然而实际测试发现是一个小于100000的数字,说明voilatile不能保证++操作的原子性。

 volatile关键字修饰的变量被读或者被写是使用锁来同步,并且对于volatile修饰变量的读总是可以读到任意线程对这个变量(当时)最新的写入。但是对于读并且写这样的复合操作是不具有原子性的。

volatile关键字修饰的变量具有对其写happens-before对其读的规则,因此线程总能看见任意线程对此volatile变量最新的修改。

 

volatile变量具有的特性如下

可见性:总是能够读到任意线程对volatile变量最新的修改

原子性:对单个volatile变量的读或者写具有原子性,但复合操作如++不具有原子性

 

posted @ 2016-06-29 16:50  活在夢裡  阅读(666)  评论(0编辑  收藏  举报