java多线程之volatile

本文探讨了在多线程环境中使用volatile关键字确保线程间数据一致性和可见性的原理。通过解释工作内存与主内存之间的交互,阐述了volatile如何通过内存屏障禁止指令重排,以及JVM对volatile变量的操作规范。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程间数据一致性

在这里插入图片描述
问题引述:
当前有两个线程,线程1和线程2,在各自的工作内存中,持有堆内存flag对象的副本。如何保证两个线程中flag对象是一致的呢,避免出现类似线程1中flag=1,线程2中flag=2的情况。

可见性

如何解决上面的问题呢?我们首先得知道下线程的工作原理。线程将数据从主内存copy进自己的工作内存之后,后续的读写操作,实际操作的都是工作内存中的数据,在运行到某些时刻,如释放同步锁,代码执行完毕等情况下,才会将工作内存中的数据写入主内存,在这段时间内,另一个线程读取到的数据,依然是老的结果。

所以,问题就出现在这个时间差上,也即数据修改后的结果,并不是立即写入主内存。当一个线程修改了数据之后,如果将结果立即刷新进主内存,另一个线程在需要读取这个变量的时候,不再从工作内存中去取数据,而是直接从主内存读取,这样便可实现一个线程对数据的修改,对另一个线程可见。

指令重排

为了提高执行效率,在编译成汇编语言时,编译器会对对指令进行重排序,即:
代码逻辑:a=1;b=2
汇编指令:b=2;a=1
实际执行的顺序,与我们代码写的预期顺序是不符的。

volatile关键字,是可以禁止指令重排序的,具体是怎么做的呢:使用内存屏障。

JVM定义了8中原子操作:

  • lock 锁定 : 把主内存中的一个变量标志为一个线程独享的状态
  • unlock 解锁 : 把主内存中的一个变量释放出来
  • read 读:将主内存中的变量读到工作内存中
  • load 加载:将工作内存中的变量加载到副本中
  • use 使用:当执行引擎需要使用到一个变量时,将工作内存中的变量的值传递给执行引擎
  • assign 赋值:将执行引擎收的的值赋值给工作内存中的变量
  • store 存储:将工作内存中的变量的值传到主内存中
  • write 写入:将store得到值放到主内存的变量中

JVM 对于volatile修饰的变量,会在其前面分别添加读写屏障:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值