繁体   English   中英

C ++内存排序

[英]C++ memory ordering

在一些教程中,我看到了这样的自旋锁实现

class spin_lock 
{
    atomic<unsigned int> m_spin ;

public:
    spin_lock(): m_spin(0) {}
    ~spin_lock() { assert( m_spin.load(memory_order_relaxed) == 0);}

    void lock()
    {
        unsigned int nCur;
        do { nCur = 0; }
        while ( !m_spin.compare_exchange_weak( nCur, 1, memory_order_acquire ));
    }
    void unlock()
    {
        m_spin.store( 0, memory_order_release );
    }
};

我们是否真的需要memory_order_acquire / memory_order_release标签分别用于compare_exchange_weakstore操作? 或者memory_order_relaxed在这种情况下就足够了,因为没有Synchronizes-With关系?

更新:谢谢您的解释! 我正在考虑spin_lock,没有使用它的上下文。

是的memory_order_acquire / memory_order_release是必需的。

您使用锁来保护多个线程之间的共享数据。 如果在unlock方法中不使用memory_order_release ,则可以在unlock方法后重新排序对共享数据的任何写入。 此外,如果您在lock方法中不使用memory_order_acquire ,则可以在lock方法之前重新排序对共享数据的任何读取。 所以你需要acquire/release来保护线程之间的共享数据。

spinLock.lock() // use acquire here, so any read can't reordered before `lock`

// Writes to shared data

spinLock.unlock() // use release here, so any write can't reordered after `unlock`

使用acquire/release对锁定自旋锁的线程可以看到对共享数据的所有写入。

关于memory_order_acquire / memory_order_release:考虑使用锁保护的共享数据(也称为内存位置或资源)。 我称之为“受保护的数据”。

代码需要确保当lock()返回时,调用者对受保护数据的任何访问都将读取有效值(即不是过时值)。 memory_order_aquire确保插入适当的aquire内存屏障,以便后续读取受保护数据(通过本地CPU缓存)将是有效的。 类似地,当调用unlock()时,需要memory_order_release以确保插入适当的内存屏障,以便正确同步其他缓存。

某些处理器不需要获取/释放障碍,并且对于理论示例,可能仅需要lock()中的完整屏障。 但是C ++并发模型需要足够灵活以支持许多不同的处理器体系结构。

memory_order_relaxed在析构函数中使用,因为这只是一个完整性检查,以确保当前不保持锁。 破坏锁定不会给调用者带来任何同步语义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM