volatile的内存语义

本文详细探讨了Java中的volatile关键字,它确保了变量的可见性和单线程原子性。volatile读写与锁的释放获取具有相似的内存效果,能保证特定条件下的happens-before关系。此外,volatile通过内存屏障防止指令重排序,从而增强了并发安全性。虽然volatile写操作比读操作成本高,但在某些场景下,它可以作为轻量级锁的替代品,提高性能。

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

前言

之前的文章对volatile进行了简单的介绍。volatile可以保证变量对所有线程可见,他是通过lock指令实现的。而lock指令在操作系统具体什么作用,之前介绍过,这里不再说了。今天我们将会更加深入的介绍volatile。

volatile的特性

可见性:对于一个volatile变量的读,总是能看到对这个volatile 的变量的最后的写入。(为什么之前说过了,这里不说了)
原子性:对于单个volatile变量的读写具有原子性,但是volatile++这种复合操作不具有原子性。(这个之前说过)

volatile读写建立的happens-before关系

volatile的读写和锁的释放和获取有相同的内存效果。
在这里插入图片描述
在这里插入图片描述
原本在没有voaltile的情况下,是不能保证1在34之前的,但是因为有了volatile,所以可以保证1在34之前,感觉是不是和锁的感觉有点类似呢。而为什么1在34之前呢。首先根据程序次序规则,1happens-before2,3happens-before4,由因为2happens-before3,所以根据传递性,是不是可以得出1happens-before3,4.
所以我们可以得出,线程A在写这个volatile变量之前所有可见的共享变量值都将立即变得对线程b可见。
1.线程A写一个volatile变量,实质上是线程A向接下来将要读这个volatile变量的某个线程发出了其对共享变量修改的消息。
2.线程b读一个volatile变量,实质上是线程b接收了之前某个线程发出的在写这个volatile变量之前对共享变量所作的修改消息。
3.线程a写一个volatile变量,随后线程b读这个volatile变量,这个过程实质上就是线程a通过主存向线程b发送消息。(不知道大家还知不知道,并发编程的问题就是,怎么解决线程通信,而解决方案有两种:1.共享内存 2.消息传递。共享内存其实就是通过修改共享内存的公共变量达到隐式传递消息。)

volatile内存语义实现

大家不知道是否还记得,jmm只是向as-if-else靠拢,但是并不是安全按照那个语义来的。也就是单线程也会重排序。那么上面的1怎么happens-before2呢。这就是volatile的另一个特点,会禁止部分的指令重排序。
在这里插入图片描述
从上面这个图大家可以看出,当第一个操作时volatile读的时候,之后的操作都不允许重排序,当第二个操作是volatile写的时候,之前的操作,都不允许重排序。当第一个操作时volatile写第二个操作时volatile读的时候,操作不允许重排序。
jmm实现指令禁止重排序,是使用内存屏障,所以volatile也是使用的内存屏障(之间介绍过内存屏障)。
1.volatile写之前插入一个storestore屏障
2.volatile写之后插入一个storeload屏障
3.volatile读之后插入一个loadload屏障
4.volatile读之后插入一个loadstore屏障
在这里插入图片描述
volatile写之后插入一个storeload屏障(不同这个为嘛只能防止volatile读/写重排序,而且storeload还是最全能的屏障,具有其他三个屏障的特性)。
volatile的写的消耗会比读大很多,因为写用到了storeload屏障,而这个屏障是四个屏障中性能消耗最大的一个。
volatile禁止重排序的功能,是在jsr-133之后才有的,之前的旧的内存模型没有这个语义。

总结

之前的文章介绍了,volatile的可见性,以及实现。今天主要介绍的是在可见性的基础上,又添加了一些禁止重排序的特性,当前是在一定条件下。这样,volatile如果使用的好,在一些场景下可以替代锁使用。而它的性能消耗可比锁低多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mark---小鑫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值