使用显式内存栅栏是什么意思?
为了提高性能,现代CPU通常不按顺序执行指令以最大限度地利用可用的硅(包括存储器读/写).由于硬件强制执行指令完整性,因此您不会在单个执行线程中注意到这一点.但是,对于具有易失性内存的多线程或环境(例如,内存映射I/O),这可能会导致不可预测的行为.
内存栅栏/屏障是一类指令,表示内存读/写按您期望的顺序发生.例如,"完全栅栏"表示在栅栏之后的栅栏之前进行所有读/写操作.
注意内存栅栏是硬件概念.在更高级别的语言中,我们习惯于处理互斥锁和信号量 - 这些很可能是使用低级别的内存栅栏来实现的,并且不需要明确使用内存屏障.使用内存屏障需要仔细研究硬件架构,并且在设备驱动程序中比应用程序代码更常见.
CPU重新排序与编译器优化不同 - 尽管伪像可以类似.如果可能导致不良行为(例如在C中使用volatile关键字),则需要采取单独的措施来停止编译器重新排序指令.
将我的答案复制到另一个问题,处理器为优化代码做了哪些技巧?:
最重要的一个是内存访问重新排序.
如果没有内存屏障或序列化指令,处理器可以自由重新排序内存访问.某些处理器架构限制了它们可以重新排序的程度; Alpha被认为是最弱的(即可以重新排序最多的那个).
可以在Linux内核源文档的Documentation/memory-barriers.txt中找到对该主题的非常好的处理.
大多数情况下,最好使用编译器或标准库中的锁定原语; 这些都经过了充分的测试,应该具备所有必要的内存障碍,并且可能已经非常优化(优化锁定原语很棘手;即使是专家也可能有时会弄错它们).
根据我的经验,它指的是一个内存屏障,它是一个指令(显式或隐式),用于同步多个线程之间的内存访问.
问题发生在现代侵略性编译器的组合中(它们具有重新排序指令的惊人自由,但通常对您的线程一无所知)和现代多核CPU.
对这个问题的一个很好的介绍是" '双重检查锁定'声明 ".对于许多人来说,这是一个叫醒龙的警钟.
隐含的完整内存屏障通常包含在平台线程同步例程中,它涵盖了它的核心.但是,对于无锁编程和实现自定义轻量级同步模式,您通常只需要屏障,甚至只需要单向屏障.