【问题标题】:Is it correct to use memory_order_relaxed at this code?在此代码中使用 memory_order_relaxed 是否正确?
【发布时间】:2013-12-31 11:51:51
【问题描述】:

在下面的代码中使用std::memory_order_relaxed是否正确?

#include <atomic>
#include <array>
#include <iostream>
#include <thread>

using namespace std;

int main() {
    std::atomic<int> counter(0);

    constexpr size_t thread_count = 10;
    std::array<std::thread, thread_count> threads;
    for (auto& th : threads) {
        th = std::thread([&counter]() {
            for (int j = 0; j < 100; ++j) {
/*1*/           counter.fetch_add(1, std::memory_order_relaxed);
            }
        });
    }

    for (auto& th : threads) th.join();

/*2*/ std::cout << counter.load(std::memory_order_relaxed) << std::endl;

    return 0;
}

我有一个方法调用计数器。计数器何时实际增加(/*1*/)并不重要,只要它增加一段时间就足够了。 但是当我调用atomic::load (/*2*/) 时,所做的所有计数器更改都应该是可见的。

/*1*//*2*/ 行中使用std::memory_order_relaxed 是否正确?

【问题讨论】:

    标签: c++ c++11 concurrency atomic


    【解决方案1】:

    是的,没关系。线程加入提供了必要的同步点,确保最终的load() 看到正确的值。

    【讨论】:

    • 谢谢!如果我用std::this_thread::sleep_for(some long period of time) 替换th.join(),这段代码仍然正确吗?或者我至少应该使用counter.load(std::memory_order_acquire)
    • @york.beta:不。你必须有一个同步点,例如释放/获取对。 (程序不会像这样不正确,因为您访问一个原子变量,但结果将是不可预测的。)再一次,在没有加入的情况下,无论如何,计数器的状态都是不可预测的。
    • 我对答案有同样的问题和相同的评论。谢谢@Kerrek SB!这是另一个:counter.fetch_add(0, std::memory_order_relaxed);读取计数器与通过 join()s 获得同步点相同吗?
    • 基本原理在这里:stackoverflow.com/a/8833218/643011 “保证您拥有“最新”值的唯一方法是使用读取-修改-写入操作,例如 exchange() , compare_exchange_strong() 或 fetch_add()” 但话说回来,整个问题将毫无意义,因为无论多么可能无法保证线程被调度的顺序以及编写者真正完成的顺序。即使这是一个很长的睡眠。
    猜你喜欢
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 2022-01-14
    相关资源
    最近更新 更多