在c ++ 11中使用带有std :: thread的atomics

时间:2012-10-27 19:53:55

标签: c++ multithreading gcc c++11 atomic

我有一个线程,我想坐在循环中,直到我准备退出程序,此时我希望它突破循环并退出以便我可以在其上调用std::thread::join 。在c ++ 03的时代,我只会使用一个受锁保护的bool来告诉线程什么时候退出。这次我以为我会利用新的原子库(特别是std::atomic_bool),但我遇到了麻烦。以下是我的测试用例:

#include <atomic>
#include <thread>
#include <cstdio>

using namespace std;

void setBool(atomic_bool& ab)
{
    ab = true;
}

int main()
{
    atomic_bool b;
    b = false;
    thread t(setBool, b);
    t.join();
    printf("Atomic bool value: %d\n", b.load());
    return 0;
}

当我尝试编译时,thread t的声明吐出this怪物。错误的核心部分似乎是:

  

从'std :: atomic_bool'类型的右值开始无效初始化'std :: atomic_bool&amp;'类型的非const引用

为什么我无法获得对atomic_bool的引用?我该怎么做呢?

3 个答案:

答案 0 :(得分:13)

您必须明确地将ref传递给您的线程。使用std::ref会创建一个std::reference_wrapper,它是可复制的,并会将ref带到您的函数中。

thread t(setBool, std::ref(b));

否则它会尝试复制你的原子,这是不可复制的。

答案 1 :(得分:4)

正如bamboon解释的那样,如果你真的希望它们通过std::ref的变量参数构造函数通过引用传递,你必须用std::thread包装对象。 (这同样适用于std::async。)为了避免这种违反直觉的行为,您可以使用lambda,其行为与您期望的完全相同。只需使用它来创建线程:

thread t([&]{ setBool(b); });

使用lambda,当你想通过引用传递参数时,不需要ref / cref废话。

答案 2 :(得分:1)

我也遇到了这个问题,我认为你也可以通过将地址传递给原子来解决你的问题:

std::atomic<bool> b{false};
std::thread t(setBool, &b);

你的函数使用指向原子的指针:

void setBool(std::atomic<bool>* ab)

我不确定接受的做法是什么,我想你可以通过这种方式将空指针传递给原子,但我不确定你为什么要这样做。