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当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取 | 锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住 |
使用范围 | 仅能使用在变量级别 | 可以使用在变量、方法、和类级别的 |
实现功能 | 仅能实现变量的修改可见性,不能保证原子性 | 可以保证变量的修改可见性和原子性 |
造成线程阻塞情况 | 不会造成线程阻塞 | 可能会造成线程阻塞 |
是否会被编译器优化 | 标记的变量不会被编译器优化 | 标记的变量可以被编译器优化 |