4月20:线程安全

image.png
  1. Volatile 与 内存屏障 与 CPU重排序
  (1)  volatile 只能保证编译器不会做乱序执行优化,无法保证CPU执行时不乱序执行。

  (2)   要保证CPU执行时不乱序执行,需要内存屏障(memory barrier),形式如下:
           _asm_  _volatile_("":::"memory") 其中的组成详解如下:
                        _asm_         用于指示编译器在此插入汇编语句;
                       _volatile_   等同于c语言的volatile
        :::       表示这个是空指令。

memory 强制gcc编译器假RAM所有的内存单元均被汇编指令修改,这样CPU中的registers 和cache中以缓存的内存单元中的数据将作废。CPU将不得不在需要的时候重新读取内存中的数据,这样就阻止了又将registers,cache中的数据用于优化指令而比曼去访问内存!!

      对于内存屏障封装最常见的宏为: xxx_mb(), barrier() 等:
            mb()    适用于多处理器和单处理器的内存屏障
            rmb()  适用于多处理器和单处理器的读内存屏障
           wmb()  适用于多处理器和单处理器的写内存屏障

           smp_ mb()    适用于多处理器的内存屏障
           smp_rmb()  适用于多处理器的读内存屏障
           smp_wmb()  适用于多处理器的写内存屏障.

前提:读可以多线程,写必须单线程,如果是多线程写,则做不到无锁。 内存屏障的核心是:一写多读,完全无锁,对于多线程写的情况,内存屏障完全无用。 在多核CPU中,改过的值可能还在当前CPU的缓存中,没有刷新到内存中,内核屏障就是要强制把这个值刷新到内存中。

 (3) CPU指令重排:多核的CPU中才会出现!!! 指令重排 无法逾越 内存屏障

为什么CPU 与 内存之间会有缓存 :程序中CPU计算 与 内存交互,CPU计算速度 远远高于 与内存交互的速度,所以为了提高速度而引入了缓存,缓存一致性是保证数据准确性的基础。在多处理器时,单个CPU对缓存的改动,需要通知其他CPU,所以CPU不仅要控制自己的读写操作,还要监听其他CPU发出的通知,从而保证数据的最终一致性!!

CPU性能优化手段----运行时指令重排:

当CPU写缓存时发现缓存被其他CPU占用,为了提高CPU性能,遵循as-if-serial语义 可将后面的读缓存命令优先执行。其中as-if-serial语义:不管怎么重排,(单线程)程序的执行结果不能改变。

CPU高速缓存下出现的问题:

缓存中的数据和主内存的数据并不是实时同步的,各个CPU间的缓存数据也不是实时同步的,在同一时间内存地址的数据值可能不一致。 解决方案:读内存屏障。

   CPU重排出现的问题:

多核多线程中,指令逻辑无法分辨因果关系,可能出现乱序执行,导致程序运行结果出错。 解决方案:写内存屏障。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容