java 中的volatile关键字
2021/12/12 22:21:28
本文主要是介绍java 中的volatile关键字,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1.volatile实现可见性的原理是什么?
有volatile变量修饰的共享变量进行写操作的时候汇编代码会多出一个Lock前缀指令。
在该指令下,多核处理器会引发两件事:
将当前处理器缓存行的数据写回系统内存
这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效
这里需要简单了解CPU缓存一致性问题:多核处理器环境下,每个CPU都有自己的缓存行,缓存了内存中的数据,要维护多个CPU中缓存的数据一致性,就需要解决两个问题:
一是写传播(某个CPU里的cache数据更新时,需要传播到其他CPU的cache中);
二是事务的串行化执行(在某个CPU里对数据的修改,在其他CPU中看起来顺序是一样的,也就是要引入近似[锁]的概念,保证同一时刻只有一个CPU可以对数据做修改);
写传播是通过[总线嗅探]完成的:通过总线把修改数据的事件广播通知给其他所有的核心,每个CPU核心都会监听总线上的广播事件,并检查是否有相同的数据在自己的Cache里面;而事务的串行化则通过[MESI协议]来完成。
MESI(Modified(已修改)、Exclusive(独占)、Shared(共享)、Ivalidated(已失效))协议中,如果要修改一个共享数据,不能直接修改,要先向其他CPU广播一个请求,把其他CPU cache中对应的数据状态改为Invalidated;以后其他CPU在读取标记为Invalidated的数据时,需要强制从内存中读取数据。
Java技术迷
2.演示volatile的可见性
public class VolatileDemo {
static int flag = 1; // 定义一个共享变量
public static void main(String[] args) {
// 两个线程,一个线程负责读取flag的值,另一个线程负责修改flag的值
new Thread(){
int localflag = flag;
@Override
public void run() {
while(true){
//flag被修改后就跟localflag不一样了
if(localflag!=flag){
System.out.println("读到了flag修改后的值:"+ flag);
//把读到的值赋值给本地变量
localflag = flag;
}
}
}
}.start();
new Thread(){
int localflag = flag;
@Override
public void run() {
while (true){
//一直对flag的值进行修改
System.out.println("对flag的值进行修改:"+ ++localflag);
flag = localflag;
//休眠一秒更好地观察结果
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
可以看到另一个线程并不能及时读取到被修改的值。
共享变量用volatile修饰后:
public class VolatileDemo {
static volatile int flag = 1;
public static void main(String[] args) {
// 两个线程,一个线程负责读取flag的值,另一个线程负责修改flag的值
new Thread(){
int localflag = flag;
@Override
public void run() {
while(true){
//flag被修改后就跟localflag不一样了
if(localflag!=flag){
System.out.println("读到了flag修改后的值:"+ flag);
//把读到的值赋值给本地变量
localflag = flag;
}
}
}
}.start();
new Thread(){
int localflag = flag;
@Override
public void run() {
while (true){
//一直对flag的值进行修改
System.out.println("对flag的值进行修改:"+ ++localflag);
flag = localflag;
//休眠一秒更好地观察结果
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
可以看到用volatile修饰后,每次另一个线程总能读取到修改后的值。
这篇关于java 中的volatile关键字的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-06小米11i印度快充版ROM合集:极致体验,超越期待
- 2024-10-06【ROM下载】小米11i 5G 印度版系统, 疾速跃迁,定义新速度
- 2024-10-06【ROM下载】小米 11 青春活力版,青春无极限,活力全开
- 2024-10-05小米13T Pro系统合集:性能与摄影的极致融合,值得你升级的系统ROM
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求