我可以在这里使用无线程同步吗?

时间:2017-01-07 16:43:13

标签: c++ multithreading c++11 mutex

我正在研究互斥体。

我想出了这个似乎没有任何同步的例子。

#include <cstdint>
#include <thread>

#include <iostream>

constexpr size_t COUNT = 10000000;

int g_x = 0;

void p1(){
    for(size_t i = 0; i < COUNT; ++i){
        ++g_x;
    }
}

void p2(){
    int a = 0;

    for(size_t i = 0; i < COUNT; ++i){
        if (a > g_x){
            std::cout << "Problem detected" << '\n';
        }

        a = g_x;
    }
}

int main(){
    std::thread t1{ p1 };
    std::thread t2{ p2 };

    t1.join();
    t2.join();

    std::cout << g_x << '\n';
}

我的假设如下:

线程1更改g_x的值,但它是唯一更改该值的线程,因此从理论上讲这可能是正确的。

线程2读取g_x的值。读取假设在x86和ARM上是原子的。所以也一定没有问题。我有几个读线程的例子,它也可以正常工作。

换句话说,写入不是共享的,读取是原子的。

这些假设是否正确?

1 个答案:

答案 0 :(得分:4)

这里确实存在数据竞争:g_x不是std::atomic;它由一个线程写入,并由另一个线程读取。所以结果是不确定的。

请注意,CPU内存模型只是交易的一部分。如果您没有正确声明共享变量,编译器可能会进行各种优化(使用寄存器,重新排序等)。

至于互斥体,你在这里不需要。将g_x声明为原子应该删除UB并保证线程之间的正确通信。顺便说一句,即使你使用原子,p2中的for也可以被优化掉,但我认为这只是一个简化的代码而不是真实的东西。