记忆屏障是否适用于此锁

Are the memory barriers correct for this lock?

本文关键字:适用于 是否 记忆      更新时间:2023-10-16

这是正确的吗?我假设在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()函数是正确同步的。