Volatile

  • 被volatile修饰的变量能够保证每个线程能够获取该变量的最新值,从而避免出现数据脏读的现象。

 

一、Volatile使用


private volatile boolean flag = false;

二、Volatile特性及原理


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

1. 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

            锁住缓存内存,让数据直接写到系统内存。
            当使用volatile关键字会强制将修改的值立即写入内存。而且会致使线程的工作内存中被volatile修饰的变量失效。
            由于线程的工作内存中被volatile修饰的变量失效,因此要读取/写入被volatile修饰的变量,只能去主存中读取/写入。
        -----------------------------------------------------------------
            注:如果对声明了volatile变量进行写操作时,JVM会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据写到系统内存中。

2. 内存屏障,禁止进行指令重排序
        volatile关键字禁止指令重排序有两层意思:
            (1)前面的操作已经全部进行了:当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;
            (2)volatile变量的读写操作不能放前也不能放后:在进行指令优化时,不能将在对volatile变量的读操作或者写操作的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。
        -----------------------------------------------------------------
            相当于一个内存屏障(也称为内存栅栏),它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它面前的操作已经全部完成。
            

备注:
- 1.Volatile无法保证原子性。

        Volatile能保证可见性没错,但可见性只能保证每次读取的是最新的值,无法保证对变量的操作的原子性。

- 2.synchronized 与 Volatile 区别?

区别

Volatile

synchronized

本质原理

本质是告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取

锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住

使用范围

仅能使用在变量级别

可以使用在变量、方法、和类级别的

实现功能

仅能实现变量的修改可见性,不能保证原子性

可以保证变量的修改可见性和原子性

造成线程阻塞情况

不会造成线程阻塞

可能会造成线程阻塞

是否会被编译器优化

标记的变量不会被编译器优化

标记的变量可以被编译器优化