多线程函数传参慎用引用

c++11引入的多线程非常方便,结合lambda表达式可以快速将单线程程序改为多线程。
c++使用引用传参是一个常用的技巧,可以减少数据拷贝,有时也用来传递返回值。
但是在多线程函数中,使用引用作为参数要注意引用值是否会改变。
在下面的示例程序中,for循环中的a传递给的每个线程都是同一个地址,当func函数执行慢于for循环时,该值即会发生改变。
由于func拿到参数一般都会立即使用,很可能会出现多数情况没有bug,只有偶尔才触发bug的隐秘情况。
传拷贝就不会出现这样的问题;
当没有使用多线程时,由于程序顺序执行,func执行完毕后程序for才会迭代,也不会出现这样的问题。
#include <cstdio>
#include <vector>
#include <thread>

 

void func(const int& a)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(5));
    printf("value is %d, address is %X\n", a, &a);
}

 

int main()
{
    std::vector<std::thread> threads;
    for(inti=1;i<=5;i++)
    {
        int a = i * 10;
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        //auto th = std::thread([&](){func(a);});
        auto th = std::thread([](int&b){func(b);}, std::ref(a));
        //th.join();
        threads.emplace_back(std::move(th));
    }
    for(auto& th: threads)
        th.join();
    return 0;
}

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注

14 − 4 =