在C++中,获取/释放原子访问和结合围栏的放松访问之间有什么有效的区别吗
In C++, is there any effective difference between a acquire/release atomic access and a relaxed access combined with a fence?
具体而言,之间是否存在任何有效差异
i = a.load(memory_order_acquire);
或
a.store(5, memory_order_release);
和
atomic_thread_fence(memory_order_acquire);
i = a.load(memory_order_relaxed);
或
a.store(5, memory_order_relaxed);
atomic_thread_fence(memory_order_release);
分别?
非宽松的原子访问提供信号围栏和线程围栏吗?
在您的代码中,对于load
和store
,围栏和原子操作之间的顺序应该颠倒,然后它与独立操作类似,但存在差异。
对原子变量的获取和释放操作充当单向屏障,但方向相反。也就是说,存储/释放操作防止在它之前(在程序源中)的内存操作在它之后被重新排序,而加载/获取操作可防止后面的内存操作在它之前被重新排序。
// thread 1
// shared memory operations A
a.store(5, std::memory_order_release);
x = 42; // regular int
// thread 2
while (a.load(std::memory_order_acquire) != 5);
// shared memory operations B
内存操作A不能向下移动到store/release
以下,而内存操作B不能向上移动到load/acquire
以上。一旦线程2读取5,内存操作A对B可见,同步就完成了
作为单向屏障,对x
的写入可以加入甚至先于内存操作a,但由于它不是获取/释放关系的一部分,线程2无法可靠地访问x
。
用独立的线程围栏和宽松的操作取代原子操作是类似的:
// thread 1
// shared memory operations A
std::atomic_thread_fence(memory_order_release);
a.store(5, std::memory_order_relaxed);
// thread 2
while (a.load(std::memory_order_relaxed) != 5);
std::atomic_thread_fence(memory_order_acquire);
// shared memory operations B
这实现了相同的结果,但一个重要的区别是,两个围栏都不是单向屏障;如果他们这样做了,则到a
的原子存储可以在释放围栏之前重新排序,来自a
的原子加载可以在获取围栏之后重新排序,并且这将打破同步关系。
一般情况下:
- 一个独立的发布围栏可以防止前面的操作被后面的(原子)存储重新排序
- 独立的获取围栏可以防止以下操作被前面的(原子)加载重新排序
该标准允许采集/释放围栏与采集/释放操作混合使用。
非松弛原子访问是否提供信号围栏和线程围栏?
我不完全清楚你在这里问什么,因为线程围栏通常与宽松的原子操作一起使用,但是std::thread_signal_fence
类似于std::atomic_thread_fence
,不同之处在于它应该在同一线程内操作,并且因此编译器不生成用于线程间同步的CPU指令。它基本上只充当编译器的屏障。
您需要
atomic_thread_fence(memory_order_release);
a.store(5, memory_order_relaxed);
和
i = a.load(memory_order_relaxed);
atomic_thread_fence(memory_order_acquire);
更换
a.store(5, memory_order_release);
和
i = a.load(memory_order_acquire);
非松弛原子访问确实提供了信号围栏以及线程围栏。
相关文章:
- 对于C++随机访问迭代器(矢量迭代器),迭代器之间的差异是如何计算的?
- 两个类之间的交叉访问
- 互锁变量访问(在布尔值上)和 std::atomic_flag 之间的区别
- C++ 静态成员变量 - 文件之间的访问
- 使用 NamedPipe 访问 Windows 服务之间的安全性
- NSMutabledictionary和STD :: Map的访问操作员之间的差异
- 内存泄漏,访问释放内存和双重免费之间有什么区别
- 在C++中,获取/释放原子访问和结合围栏的放松访问之间有什么有效的区别吗
- C 如何在实例之间访问类成员功能
- 基于两个程序之间的事件触发器访问数据(内存)
- 这是对序列点之间同一对象的多次访问定义良好的行为
- 访问友元类之间的函数变量
- 如何在类之间访问变量
- 在C++中如何在类方法之间访问静态局部变量的值
- 私有成员的常量访问器之间的比较
- 访问结构内容,当类型和内容在不同 DLL 之间变化时
- 访问存储在开始指针和结束指针之间的值
- 访问聚合器类中的类之间共享的变量
- 访问器方法和赋值器方法之间的区别是什么
- 根据构造函数的可访问性在函数之间进行选择的模板方法