什么是记忆围栏?

时间:2008-11-13 09:30:33

标签: concurrency memory-fences

使用显式内存栅栏是什么意思?

5 个答案:

答案 0 :(得分:94)

为了提高性能,现代CPU通常不按顺序执行指令,以最大限度地利用可用的芯片(包括存储器读/写)。由于硬件强制执行指令完整性,因此您不会在单个执行线程中注意到这一点。但是,对于具有易失性内存的多线程或环境(例如,内存映射I / O),这可能会导致不可预测的行为。

内存栏/屏障是一类指令,表示内存读/写按您期望的顺序发生。例如,“完全围栏”表示在围栏之后的围栏之前进行所有读/写操作。

注意内存栅栏是硬件概念。在更高级别的语言中,我们习惯于处理互斥锁和信号量 - 这些很可能是使用低级别的内存栅栏来实现的,并且不需要明确使用内存屏障。使用内存屏障需要仔细研究硬件架构,并且在设备驱动程序中比应用程序代码更常见。

CPU重新排序与编译器优化不同 - 尽管伪像可能类似。如果可能导致不良行为(例如在C中使用volatile关键字),则需要采取单独的措施来停止编译器重新排序指令。

答案 1 :(得分:15)

my answer复制到另一个问题,What are some tricks that a processor does to optimize code?

  

最重要的一个是内存访问重新排序。

     

缺少内存屏障或序列化指令,处理器可以自由重新排序内存访问。某些处理器架构限制了它们可以重新排序的程度; Alpha被认为是最弱的(即可以重新排序最多的那个)。

     

可以在Documentation/memory-barriers.txt的Linux内核源文档中找到对该主题的非常好的处理。

     

大多数情况下,最好使用编译器或标准库中的锁定原语;这些都经过了充分的测试,应该具备所有必要的内存障碍,并且可能已经非常优化(优化锁定原语很棘手;甚至专家也可能有时会弄错)。

答案 2 :(得分:6)

根据我的经验,它引用了memory barrier,它是一个指令(显式或隐式),用于同步多个线程之间的内存访问。

问题出现在现代侵略性编译器的组合中(它们具有重新排序指令的惊人自由,但通常对您的线程一无所知)和现代多核CPU。

对问题的一个很好的介绍是“The 'Double-Checked Locking is Broken' Declaration”。对于许多人来说,这是一个叫醒龙的警钟。

隐式完全内存屏障通常包含在平台线程同步例程中,它涵盖了它的核心。但是,对于无锁编程和实现自定义轻量级同步模式,您通常只需要屏障,甚至只需要单向屏障。

答案 3 :(得分:1)

Wikipedia knows all...

  

记忆障碍,也称为膜   或记忆围栏,是一类   导致中心的指示   处理单元(CPU)强制执行   对内存的排序约束   之前和之后发布的操作   障碍指导。

     

CPU采用性能优化   这可能导致无序   执行,包括内存负载和   商店运营。记忆操作   重新排序通常不被注意   在单个执行线程中,   但导致不可预测的行为   并发程序和设备驱动程序   除非仔细控制。最正确   排序约束的本质是   硬件依赖,并由   架构的记忆模型。一些   架构提供了多种功能   执行不同的障碍   订购约束。

     

通常使用内存屏障   在实现低级机器时   在共享的内存上运行的代码   多个设备。这样的代码包括   同步原语和   无锁数据结构   多处理器系统和设备   与计算机通信的驱动程序   硬件

答案 4 :(得分:0)

memory fencememory barrier)是一种用于同步的无锁机制。

问题是订购,共享资源和缓存。处理器或编译器能够重新排序程序指令(程序员顺序)以进行优化。它在多线程环境中产生副作用。这就是为什么引入memory barrier来保证程序正常运行的原因。速度较慢,但​​可以解决此类问题

[Java Atomicity, Visibility, Ordering]