背景
多线程开发中,不少见 volatile,其很典型的标记就是可见性,接下来一起了解一下其原理吧
定义
volatile 是轻量级的 synchronized,它在多处理器开发中保证了共享变量的“可见性"
可见性的意思是一个线程修改一个共享变量时,另外一个线程能读到这个修改的值
volatile 的使用比锁的成本更低,因为它不会引起线程上下文的切换和调度
术语
- 内存屏障
是一组处理器指令,用于实现对内存操作的顺序限制
- 缓存行
缓存中可以分配的最小存储单位。
实现原理
有 volatile 修饰的变量,会在进行写操作时,执行 Lock 前缀的指令,会引发下面两件事情
- 将当前处理器缓存行的数据写回到系统内存
当前处理器会独占该缓存行;Lock指令会锁缓存,而不是锁总线
假如Lock的缓存已经才内部处理器中,则不会执行Lock指令
- 这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效
大多数处理器使用MESI(修改、独占、共享、无效)控制协议(有兴趣的同学可以去了解一下)去维护内部缓存和其他处理器缓存的一致性
多核处理器系统进行操作时,处理器能嗅探其他处理访问系统内存和她们的内部缓存
处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的缓存的数据在总线上保持一致
如果通过一个处理器来检测其他处理器打算写内存地址,而这个地址当前处于共享状态,那么正在嗅探的处理器将使它的缓存行无效,在下次访问相同内存地址时,强制执行缓存行填充
volatile优化
追加字节
volatile是锁缓存行的,如果是64位处理器,那么就会锁住64个字节
假如两个变量都在同一个缓存行,那么每次操作其中一个变量就会锁住两个变量了
优化方案:在两个变量间加上60位,则不会造成缓存行锁定
不需要字节追加的情况
- 缓存行非64字节宽的处理器:比如32位的处理器
- 共享变量不会被频繁地写:不会被频繁写的话,锁的几率就非常小了
喜欢的同学多多关注微信公众号