写点什么

图解 Volatile 原理三

作者:悟空聊架构
  • 2021 年 12 月 11 日
  • 本文字数:802 字

    阅读完需:约 3 分钟

你好呀,我是悟空呀~上篇我们讲到用 volatile 修饰的变量,当某线程更新变量后,其他线程也能感知到。那为什么其他线程能感知到变量更新?


其实这里就是用到了“窥探(snooping)”协议。在说“窥探(snooping)”协议之前,首先谈谈缓存一致性的问题。

缓存一致性

当多个 CPU 持有的缓存都来自同一个主内存的拷贝,当有其他 CPU 偷偷改了这个主内存数据后,其他 CPU 并不知道,那拷贝的内存将会和主内存不一致,这就是缓存不一致。那我们如何来保证缓存一致呢?这里就需要操作系统来共同制定一个同步规则来保证,而这个规则就有 MESI 协议。


如下图所示,CPU2 偷偷将 num 修改为 2,内存中 num 也被修改为 2,但是 CPU1 和 CPU3 并不知道 num 值变了。


MESI

当 CPU 写数据时,如果发现操作的变量是共享变量,即在其它 CPU 中也存在该变量的副本,系统会发出信号通知其它 CPU 将该内存变量的缓存行设置为无效。如下图所示,CPU1 和 CPU3 中 num=1 已经失效了。



当其它 CPU 读取这个变量的时,发现自己缓存该变量的缓存行是无效的,那么它就会从内存中重新读取。


如下图所示,CPU1 和 CPU3 发现缓存的 num 值失效了,就重新从内存读取,num 值更新为 2。


总线嗅探

那其他 CPU 是怎么知道要将缓存更新为失效的呢?这里是用到了总线嗅探技术。


每个 CPU 不断嗅探总线上传播的数据来检查自己缓存值是否过期了,如果处理器发现自己的缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置为无效状态,当处理器对这个数据进行修改操作的时候,会重新从内存中把数据读取到处理器缓存中。


总线风暴

总线嗅探技术有哪些缺点?


由于 MESI 缓存一致性协议,需要不断对主线进行内存嗅探,大量的交互会导致总线带宽达到峰值。因此不要滥用 volatile,可以用锁来替代,看场景啦~


作者简介:悟空,8 年一线互联网开发和架构经验,用故事讲解分布式、架构设计、Java 核心技术。《JVM 性能优化实战》专栏作者,开源了《Spring Cloud 实战 PassJava》项目,公众号:悟空聊架构。本文已收录至 www.passjava.cn

发布于: 8 小时前阅读数: 7
用户头像

用故事、大白话讲解Java、分布式、架构设计 2018.05.06 加入

公众号:「悟空聊架构」 【个人博客】www.passjava.cn 【开源项目】基于 SpringCloud 的一套面试刷题系统 【Github】https://github.com/Jackson0714/PassJava-Platform

评论

发布
暂无评论
图解 Volatile 原理三