为什么内存屏障不只阻止每个特定内存地址的指令?
Why don't memory barriers only block instructions per specific memory address?
据我所知,内存屏障将"分离"加载/存储(取决于使用的屏障类型),而不考虑与"fenced"指令相关的内存地址。因此,如果我们有一个原子自增对象,周围是load和store:
LOAD A
STORE B
LOAD C
LOCK ADD D ; Assume full fence here
LOAD E
STORE F
操作A、B和C的指令必须在D之前完成;E和F必须在d之后才能开始
但是,由于LOCK只应用于地址D,为什么要限制其他指令呢?在电路中是否太复杂而无法实现?还是另有原因?
基本原因是因为fence的基本意图是强制排序,所以如果fence只影响对其应用的特定项的读/写,则它将无法完成其工作。
例如,您经常会遇到这样的模式:
prepare some data
signal that the data is ready
:
consume some data
signal that the memory used for the data is now free
在这种情况下,用作"信号"的内存位置可能是你要用栅栏保护的东西——但它不是唯一真正需要保护的东西。
在第一种情况下,我必须确保所有写数据的代码都被执行,并且只有在所有代码都完成之后,才会设置信号。
另一个线程可以看到信号被设置。基于此,它知道它可以读取与信号相关的所有数据,而不仅仅是信号本身。如果篱笆只影响信号本身,这意味着其他正在写数据的代码可能仍然在信号之后执行——然后我们会在写数据的代码和试图读取数据的其他代码之间发生冲突。理论上,我们可以通过在写入的每个数据块周围使用栅栏来解决这个问题。在现实中,我们几乎肯定希望避免这种情况——栅栏是相当昂贵的,所以我们通常更喜欢写入大量的数据,然后使用单个栅栏来指示整个内存"块"已经准备好了。
相关文章:
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 为什么 vector 的随机访问迭代器给出与指针不同的内存地址?
- 使用内存地址访问结构的属性值
- 为什么C++总是显示十六进制内存地址,而不仅仅是整数?
- 将布局映射到内存地址
- 为什么同一个变量的内存地址不同?
- 无法将内存地址转换为值
- 给定特定内存地址的数组的动态内存分配
- 在 Microsoft Access SQL 中调用自定义 DLL 函数时传递的内存地址无效
- 获取 R 数据帧的内存地址
- c++ 编译器是否保护常量内存地址免受任何更改?
- 如何防止矢量的内存地址更改
- cout 打印内存地址而不是值
- 如何运行外部程序,向其传递内存地址以读取/写入?
- 循环中的变量被设置为下一个数组的元素始终具有相同的内存地址?
- 重载 ostream << 运算符,指针作为参数,导致输出上的内存地址
- C++在变量的内存地址上做什么来"deallocate"它?
- 在指向现有内存地址的 hpp 文件中声明成员函数的最佳方法
- 为什么我无法获取 MSVS2019 / C++ 中字符或uint8_t变量的内存地址?