volatile关键字详解(从缓存一致性谈起)

本文详细解析了Java中的volatile关键字,从缓存一致性角度出发,介绍了MESI协议,并通过实例说明volatile如何保证数据的可见性,但不保证原子性。在多线程环境下,volatile能防止共享变量的不可见性,但无法确保操作的原子性,可通过synchronized实现原子操作。

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

在讲解volatile关键字之前,我们先来看看操作系统中缓存一致性的概念。

众所周知,cpu的运行速度是远高于主存的读写速度的,在运行过程中,为了交换数据,cpu必须频繁的进行数据的读写操作,主存读写速度慢造成了cpu运行的吞吐量减少。为了解决这一问题,现在的机器都会在添加一层高速缓存(其实不止一层,有多层).以后每次cpu进行读写操作时,都直接和高速缓存交互,之后在将高速缓存中的数据回刷到主存中。在单线程情况下这没有任何问题,但在多线程环境下这会带来一些隐患。因为这会造成每个线程更改了自己高速缓存中的数据时(即使将这个更改的数据从缓存中刷回主存),其他变量读取的仍是最开始的自己高速缓存中的数据,这就造成了数据的不可见性。为了预防数据不可见性,在硬件方面有一个缓存一致性协议协议。其中最出名的MESI协议。

缓存一致性协议(MESI):

    当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时, 发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读。

在jvm中,所有变量都存在主存当中,每个线程都有自己的工作内存(也就是前面说的高速cache)。也就是说,当访问一个共享变量时,多个java线程在自己的工作内存中都会有这个共享变量的一份副本。当某个线程更改了自己工作内存中更新了数据时,此时这个线程阻塞了或者其他原因,没有及时将这个更新的数据刷回主存,那么其他线程再从主存或自己的工作缓存中读取的数据还是原来旧值,也就是说,

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值