你真的了解 volatile 关键字吗?(4)

mov    0xc(%r10),%r8d ; Load
inc    %r8d          ; Increment
mov    %r8d,0xc(%r10) ; Store
lock addl $0x0,(%rsp) ; StoreLoad Barrier

lock 前缀指令实际上相当于一个内存屏障(也叫内存栅栏),内存屏障会提供 3 个功能:

它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成(满足禁止重排序)
    它会强制将对缓存的修改操作立即写入主存(满足可见性)
    如果是写操作,它会导致其他 CPU 中对应的缓存行无效(满足可见性)

volatile 变量规则是 happens-before(先行发生原则)中的一种:对一个变量的写操作先行发生于后面对这个变量的读操作。(该特性可以很好解释 DCL 双重检查锁单例模式为什么使用 volatile 关键字来修饰能保证并发安全性)

变量声明为 volatile 类型时,编译器与运行时都会注意到这个变量是共享的,不会将该变量上的操作与其他内存操作一起重排序。volatile 变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取 volatile 类型的变量时总会返回最新写入的值。

在访问 volatile 变量时不会执行加锁操作,也就不会使执行线程阻塞,因此 volatile 变量是比 sychronized 关键字更轻量级的同步机制。

加锁机制既可以确保可见性和原子性,而 volatile 变量只能确保可见性。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/e9eb1db51192fc09e066c4aeca17a875.html