多线程有时会给出不同的输出

multithreading gives different output sometimes

我目前正在尝试更好地理解多线程,并且正在尝试使用 std::thread。

我有这段代码:

volatile int m = 0;
void ThdFun(int i)
{
    for (int j = 0; j < i; ++j) {
        m++;
        //std::cout << "hello1 " << m << " " <<std::endl;
    }
    //std::cout << "Hello World from thread " << i <<"  " << std::endl;
}
int main(){
    int var = 100000; //changes when i want to experiment with diff values

    std::thread t1(ThdFun, var);
    std::thread t2(ThdFun, var);
    t1.join();
    t2.join();
    std::cout << "final result of m: " << m << std::endl;

    if ((var * 2) == m) {
        std::cout << "CORRECT" << std::endl;
    }
    else
        std::cout << "INCORRECT" << std::endl;
    return 0;
}

我注意到,如果我的 var = 2var =50,我得到正确的输出(分别是 4 和 100)

但是当我将 var 设为 100000 之类的大数字时,我会得到 100000-200000 范围内的任何值,而我预计会得到 200000。我想知道为什么会这样,因为我的理解 'join()' 函数不应该让它按顺序运行吗?另外,为什么 'smaller' 数字的输出很好,但对于更大的数字却变得不可预测?是 1 个线程完成并因此退出程序还是什么?

有人能解释一下是什么导致了大数字的这种不同输出,以及为什么 join() 不能很好地处理大数字吗?

谢谢!

您的问题是 m++; 行。它真正的作用是这样的:

  1. 从内存中读取 m 到寄存器中
  2. 增加寄存器值
  3. 将寄存器值写回m

您的代码的问题是对 m 的访问在线程之间不同步,因此一个线程可能会读取 m(第 1 步)并且在它到达之前写回增量值(第 3 步),另一个线程已读取 m.

的旧值

在那种情况下,两个线程都读取并递增该值,就像另一个线程递增它之前的值一样,因此您失去了一个递增。

解决这个问题的方法是添加同步。

还好这个很简单,把m的定义改成std::atomic_int就可以了。当声明变量atomic时,语言保证m++操作不能被另一个线程中断。

atomic 的替代方法是使用互斥锁,但如果只有一次访问,则最好使用 atomic。