volatile的应用与原理

背景

多线程开发中,不少见 volatile,其很典型的标记就是可见性,接下来一起了解一下其原理吧

定义

volatile 是轻量级的 synchronized,它在多处理器开发中保证了共享变量的“可见性"

可见性的意思是一个线程修改一个共享变量时,另外一个线程能读到这个修改的值

volatile 的使用比锁的成本更低,因为它不会引起线程上下文的切换和调度

术语

  • 内存屏障

是一组处理器指令,用于实现对内存操作的顺序限制

  • 缓存行

缓存中可以分配的最小存储单位

实现原理

有 volatile 修饰的变量,会在进行写操作时,执行 Lock 前缀的指令,会引发下面两件事情

  • 将当前处理器缓存行的数据写回到系统内存

当前处理器会独占该缓存行;Lock指令会锁缓存,而不是锁总线

假如Lock的缓存已经才内部处理器中,则不会执行Lock指令

  • 这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效

大多数处理器使用MESI(修改、独占、共享、无效)控制协议(有兴趣的同学可以去了解一下)去维护内部缓存和其他处理器缓存的一致性

多核处理器系统进行操作时,处理器能嗅探其他处理访问系统内存和她们的内部缓存

处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的缓存的数据在总线上保持一致

如果通过一个处理器来检测其他处理器打算写内存地址,而这个地址当前处于共享状态,那么正在嗅探的处理器将使它的缓存行无效,在下次访问相同内存地址时,强制执行缓存行填充

volatile优化

追加字节

volatile是锁缓存行的,如果是64位处理器,那么就会锁住64个字节

假如两个变量都在同一个缓存行,那么每次操作其中一个变量就会锁住两个变量了

优化方案:在两个变量间加上60位,则不会造成缓存行锁定

不需要字节追加的情况
  • 缓存行非64字节宽的处理器:比如32位的处理器
  • 共享变量不会被频繁地写:不会被频繁写的话,锁的几率就非常小了

喜欢的同学多多关注微信公众号
volatile的应用与原理