volatile关键字的原理,作用,使用

1.volatile的作用

1,可以使得在多处理器环境下保证了共享变量的可见性。
2,禁止指令重排序优化

什么是可见性呢?
在多线程环境下,读和写发生在不同的线程中的时候,可能会出现:读线程不能及时的读取到其他线程写入的最新的值。这就是所谓的可见性。

volatile 关键字是如何保证可见性的?
使用【hsdis】这个工具,查看lock汇编指令,在多处理器环境下,lock 汇编指令可以基于总线锁或者缓存锁的机制来达到可见性的一个效果。

可见性的本质总结:
由于 CPU 高速缓存的出现使得 如果多个 cpu 同时缓存了相同的共享数据时,可能存在可见性问题。也就是 CPU0 修改了自己本地缓存的值对于 CPU1 不可见。不可见导致的后果是 CPU1 后续在对该数据进行写入操作时,是使用的脏数据。使得数据最终的结果不可预测。 所以要使用volatile关键字来解决这个不可见的问题。

缓存一致性
当提出cpu的告诉缓存问题,就会引出缓存一致性问题。
那么什么是缓存一致性问题呢?有了高速缓存的存在以后,每个 CPU 的处理过程是,先将计算需要用到的数据缓存在 CPU 高速缓存中,在 CPU进行计算时,直接从高速缓存中读取数据并且在计算完成之后写入到缓存中。在整个运算过程完成后,再把缓存中的数据同步到主内存。由于在多 CPU 种,每个线程可能会运行在不同的 CPU 内,并且每个线程拥有自己的高速缓存。同一份数据可能会被缓存到多个 CPU 中,如果在不同 CPU 中运行的不同线程看到同一份内存的缓存值不一样就会存在缓存不一致的问题。

解决缓存不一致的问题解决方案

  1. 总线锁
  2. 缓存锁

总线锁,简单来说就是,在多 cpu 下,当其中一个处理器要对共享内存进行操作的时候,在总线上发出一个 LOCK#信号,这个信号使得其他处理器无法通过总线来访问到共享内存中的数据,总线锁定把 CPU 和内存之间的通信锁住了,这使得锁定期间,其他处理器不能操作其他内存地址的数据,所以总线锁定的开销比较大,这种机制显然是不合适的。
如何优化呢?最好的方法就是控制锁的保护粒度,我们只需要保证对于被多个 CPU 缓存的同一份数据是一致的就行。所以引入了缓存锁,它核心机制是基于缓存一致性协议来实现的。

什么是指令重排序
是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理。
那么禁止指令重排序就相当于一个内存屏障,(内存屏障的作用可以通过防止 CPU 对内存的乱序访问来保证共享数据在多线程并行执行下的可见性
但是这个屏障怎么来加呢?回到最开始我们讲 volatile 关键字的代码,这个关键字会生成一个 Lock 的汇编指令,这个指令其实就相当于实现了一种内存屏障。

猜你喜欢

转载自blog.csdn.net/weixin_43978695/article/details/109171723