c ++ boolean compound assignment thread safety

时间:2017-11-06 14:12:55

标签: c++ multithreading c++11

如下所述,这些都不是线程安全的,因为anyTrue不是原子的,即使它可能在某些硬件上有原子性行为:

#include <thread>

bool blah() {
    return true; // or false
}

int main()
{
    bool anyTrue = false;

    // I think foo should be thread safe:
    auto foo = [&] {
        if (blah()) {
            anyTrue = true;
        }
    };

    // but I'm not confident about bar:
    auto bar = [&] {
        anyTrue &= blah();
    };

    // parallel foo:
    std::thread t1 (foo);
    std::thread t2 (foo);
    t1.join();
    t2.join();

    // parallel bar:
    std::thread t3 (bar);
    std::thread t4 (bar);
    t3.join();
    t4.join();
}

如果我anyTrue atomic,则不再编译,因为atomic没有operator&=

#include <atomic>
#include <thread>

bool blah() {
    return true; // or false
}

int main()
{
    std::atomic< bool > anyTrue (false);

    // I think foo should be thread safe:
    auto foo = [&] {
        if (blah()) {
            anyTrue = true;
        }
    };

    // but I'm not confident about bar:
    auto bar = [&] {
        anyTrue &= blah(); // error: no viable overloaded '&='
    };

    // parallel foo:
    std::thread t1 (foo);
    std::thread t2 (foo);
    t1.join();
    t2.join();

    // parallel bar:
    std::thread t3 (bar);
    std::thread t4 (bar);
    t3.join();
    t4.join();
}

1 个答案:

答案 0 :(得分:3)

这里根本没有线程安全:

  1. std::rand既不是重入也不是线程安全的。事实上,它保留了一个内部种子,所以你在这里深水。

  2. &=需要读取,修改,然后写入。那不是线程安全的。

  3. 赋值=可能不是线程安全的(例如,两个线程可能同时写入同一个内存,结果未定义。)这是一个很好的老式数据种族。谁会说你的平台上没有真正的胖bool