记忆屏障是否适用于此锁
Are the memory barriers correct for this lock?
这是正确的吗?我假设在std::atomic_flag
上应用内存排序不会为通用锁提供同步,这是正确的吗?
#include <atomic>
class Spinlock
{
public:
Spinlock(): f(ATOMIC_FLAG_INIT) {}
void lock()
{
while(f.test_and_set(std::memory_order_relaxed));
std::atomic_thread_fence(std::memory_order_acquire);
}
void unlock()
{
std::atomic_thread_fence(std::memory_order_release);
f.clear(std::memory_order_relaxed);
}
private:
std::atomic_flag f;
};
如果这是一个愚蠢的问题,我很抱歉,但我觉得std::atmoic_thread_fence
是通用锁所必需的,并且在test_and_set
上应用memory_order_acquire
和在clear
上应用memory_order_release
是不够的,但我也不确定。
总的来说,它是正确的。由于您在test_and_set函数中使用了"std::memory_order_relaxed",因此如果没有"atomic_thread_fence"调用,就不会阻止Mutex::lock之前和之后执行的操作的重新排序。由于预期"Mutex::lock"充当内存屏障,因此需要调用"atomic_thread_fence"。但我相信在"test_and_set函数"中使用"std::memory_order_aquire"也可以达到同样的效果。请参阅:http://en.cppreference.com/w/cpp/atomic/atomic_flag
通常的模式是使用test_and_set(memory_order_acquire)
和clear(memory_order_release)
。但我怀疑你已经知道了。
根据标准第29.8节[原子围栏](2):
释放围栏A与获取围栏B同步(如果存在)都对某个原子对象M进行操作的原子操作X和Y,使得A在X之前测序,X修饰M,Y在B、 Y读取X写入的值或任意一方写入的值如果X是一个释放操作。
在您的代码中,A是unlock()
函数中的围栏;X是CCD_ 10;Y是lock()
函数中的围栏;而B是CCD_ 12。因此,您的代码符合本标准这一部分的要求,因此unlock()
和lock()
函数是正确同步的。
- 确定夏令时是否适用于特定日期
- 是否有一种 STL 算法可以最后找到,但它也适用于指针?
- C++17 和更新的 std::分配器是否适用于动态数量的自定义堆?
- NRVO 是否也适用于协程?
- 约束包容是否仅适用于概念?
- std::mutex 的发布-获取可见性保证是否仅适用于关键部分?
- 使用迭代器成员函数是否仅适用于某些向量类型"empty()"?
- 别名漏洞是否适用于签名字符?
- 指针算法是否适用于迭代器?
- 保证复制 elis 是否适用于函数参数?
- 尾部调用优化是否适用于此功能?
- 值初始化是否适用于原子对象?
- 是否有适用于迭代器的数字解析函数
- 严格别名规则是否适用于跨函数调用
- Scott Meyers关于首选非成员非友元方法的建议是否适用于对象构造?
- 对函数参数的要求是否也适用于初始值设定项列表?
- 在这种情况下,(N)RVO是否适用于我的功能
- 是否有适用于张量流对象检测 API 的C++包装器
- GPU cuda 代码是否适用于多个 GPU 卡而无需任何实现
- std::copy_n 是否适用于重叠范围?