首页 > 解决方案 > C++11 memory_model_relaxed和memory_order_seq_cst的关系

问题描述

嗨,我想了解无锁工作窃取出队实现。目前,我正在阅读谷歌的灯丝here的一种实现。我最关心的是窃取操作。

template <typename TYPE, size_t COUNT>
TYPE WorkStealingDequeue<TYPE, COUNT>::steal() noexcept {
    do {
        // mTop must be read before mBottom
        int32_t top = mTop.load(std::memory_order_seq_cst);

        // mBottom is written concurrently to the read below in pop() or push(), so
        // we need basic atomicity. Also makes sure that writes made in push()
        // (prior to mBottom update) are visible.
        int32_t bottom = mBottom.load(std::memory_order_acquire);

        if (top >= bottom) { 
            // queue is empty
            return TYPE();
        }

        // The queue isn't empty
        TYPE item(getItemAt(top));
        if (mTop.compare_exchange_strong(top, top + 1,
                std::memory_order_seq_cst,
                std::memory_order_relaxed)) {
            // success: we stole a job, just return it.
            return item;
        }
        // failure: the item we just tried to steal was pop()'ed under our feet,
        // simply discard it; nothing to do.
    } while (true);
}

我想知道将初始 mtop.load 内存顺序替换为 memory_order_relaxed 并将随后的 mBottom.load 内存顺序替换为 memory_order_seq_cst 是否正确。这仍然应该保留 mtop.load 和 mBottom.load 顺序对吗?memory_order_seq_cst 标志仍然应该防止 memory_order_relaxed 通过加载操作被重新排序,对吗?

标签: c++producer-consumerdequememory-modelstdatomic

解决方案


您应该根据允许发生内存操作以保持正确性的顺序以及这些顺序如何影响线程间同步来对代码进行推理。C++std::memory_order标准允许程序员表达这样的约束,并让编译器发出必要的内存栅栏来实现这些约束。

代码已经准确地表达了它需要做的事情:mTop.load()在之前排序并将in与inmBottom.load()同步。mBottom.store()push()mBottom.load()steal()


推荐阅读