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当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取 | 锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住 |
| 使用范围 | 仅能使用在变量级别 | 可以使用在变量、方法、和类级别的 |
| 实现功能 | 仅能实现变量的修改可见性,不能保证原子性 | 可以保证变量的修改可见性和原子性 |
| 造成线程阻塞情况 | 不会造成线程阻塞 | 可能会造成线程阻塞 |
| 是否会被编译器优化 | 标记的变量不会被编译器优化 | 标记的变量可以被编译器优化 |
更多java基础总结(适合于java基础学习、java面试常规题):
总结篇(9)---字符串及基本类 (1)字符串及基本类之基本数据类型
总结篇(10)---字符串及基本类 (2)字符串及基本类之java中公共方法及操作
总结篇(12)---字符串及基本类 (4)Integer对象
总结篇(14)---JVM(java虚拟机) (1)JVM虚拟机概括
总结篇(15)---JVM(java虚拟机) (2)类加载器
总结篇(16)---JVM(java虚拟机) (3)运行时数据区
总结篇(17)---JVM(java虚拟机) (4)垃圾回收
总结篇(18)---JVM(java虚拟机) (5)垃圾回收算法
总结篇(19)---JVM(java虚拟机) (6)JVM调优
总结篇(24)---Java线程及其相关(2)多线程及其问题
总结篇(25)---Java线程及其相关(3)线程池及其问题
总结篇(26)---Java线程及其相关(4)ThreadLocal
总结篇(27)---Java并发及锁(1)Synchronized
总结篇(31)---JUC工具类(1)CountDownLatch
本文详细介绍了Java中的Volatile关键字,解释了其如何确保线程间变量的可见性,并防止指令重排序。同时对比了Volatile与synchronized的区别。
226

被折叠的 条评论
为什么被折叠?



