【问题标题】:Unexpected output from threads线程的意外输出
【发布时间】:2019-12-17 00:53:10
【问题描述】:

我有 2 个使用 lambdas 创建的线程,在 lambdas 内部,我正在调用我的函数,我在其中操作我的全局变量。

我相信当我们不使用关键字 std::ref() 将值传递给线程内的函数时,即使函数参数是引用变量,它也会按值传递。但是在我的程序中,我希望 x、y、z 变量只打印 0、0、0,因为我没有使用 std::ref 传递变量,但它有时会打印 9、0、0,其他时候会打印 0、0、0 .我在这里错过了什么吗?

请在下面找到我的代码

我已经尝试执行下面的程序来测试我的输出

#include <stdio.h>
#include <iostream>
#include <thread>

using namespace std;

int x = 0;
int y = 0;
int z = 0;

void func(int& a, int& b)
{
    for (int i = 0; i < 10000; ++i)
    {
        a += i;
        b += i;
    }

}

int main()
{
    std::thread t1([]() {
        func(x, z);

    });
    std::thread t2([]() {
        func(y, z);
    });

    cout << "x,y,z=" << x << " " << y << " " << z << " " << endl;
    t1.join();
    t2.join();
    getchar();
    return 0;
}

【问题讨论】:

  • 是什么让你认为std::refpass by reference 的必要条件?
  • 另外:您可能希望在打印结果之前加入线程 - 否则线程可能还没有完成它们的工作。
  • 不要通过引用传递给线程。如果您不能复制,请改为通过智能指针。
  • @SanderDeDycker 当我读到 std 线程时,它说通过我们将线程函数参数定义为 ref,它必须通过 std::ref 传递?对不对?
  • @VinayVinay :在某些情况下,您需要std::ref (例如,当您想复制“参考”时),但在您的情况下不需要。您的 lambda 只是访问全局变量。即使他们会捕获变量,他们也可以只是captured by reference。更多内容请参考:C++ Difference between std::ref(T) and T&?.

标签: c++ multithreading c++11


【解决方案1】:

你这里有问题。两个线程在没有保护(互斥体)的情况下写入相同的目标,因此您的结果是未定义的。

当两个线程写入同一个变量时,除非操作是原子操作,否则结果可能不是您所期望的。

例子:

int x = 0;
function 1: x++;
function 2: x++;

结果可能是 1 而不是预期的 2,因为函数 2 可能在函数 1 修改它之前将 x 读取为 0。

此外,您不必像评论所说的那样等待线程完成。

良好的做法:

  • 修改变量时,使用互斥(mutex)
  • 避免通过引用传递给线程函数,在线程有机会访问它之前,很容易让引用的变量超出范围。您可能引用了超出范围的堆栈对象。

【讨论】:

    猜你喜欢
    • 2014-03-09
    • 2014-11-30
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 2015-09-20
    • 1970-01-01
    相关资源
    最近更新 更多