std::thread的参数传递问题

实参的生命周期
给std::thread传递参数的时候要注意,参数是引用或者指针的情况下,要注意生命周期的问题

看代码

#include <iostream>
#include <thread>
#include <chrono>
#include <fstream>
using namespace std::chrono_literals;
void func_str(const std::string & str)
{
  std::this_thread::sleep_for(2s);
  std::cout << "ThreadArg data is  " << str << '\n';
}
void start_thread(void)
{
  char buffer[6] = {'a','b','c','d','e','\0'};
  std::thread t(func_str, std::string(buffer));
 // 可以测试 std::thread t(func_str, buffer); //crash
  t.detach();
}
int main(int argc, char** argv)
{
  std::thread t1(start_thread);
  t1.join();
  std::this_thread::sleep_for(3s); // 3s是字面量 since C++14  可以用 std::chrono::seconds(3)替代
  return 0;
}
我们考虑变量生命周期的问题,尤其是线程是分离的情况下,给予线程参数的线程有可能提前退出而释放资源,导致持有参数对象的线程访问了已经销毁的资源,尤其是对于局部变量。

上边的代码是为了保证线程 t 对资源的访问是独立的,所以用一个join线程t1来启动线程t,  为了观察到t线程的行为,所以又让主线程main,sleep一段时间,否则程序因为进程的结束,而回收线程资源

参数是引用类型
要使用std::ref

#include <iostream>
#include <thread>
#include <chrono>
#include <fstream>
using namespace std::chrono_literals;
class ThreadArg
{
  public:
    ThreadArg():data(123456)
    {
      std::cout<<"constructor"<<std::endl;
    }
    ThreadArg(const ThreadArg & rhs):data(rhs.data)
    {
      std::cout<<"copy constructor"<<std::endl;
    }
    ~ThreadArg()
    {
      std::cout<<"destructor"<<std::endl;
    }
    void setData(int value)
    {
      this->data = value;
    }
    void printData(int num)
    {
      std::cout << "ThreadArg data is  " << data <<"  "<<num<<'\n';
    }
  private:
    int data;
}; 
 
void func(ThreadArg & arg)
{
   arg.setData(1000);
}
int main(int argc, char** argv)
{
  ThreadArg arg;
  std::thread t1(func,std::ref(arg)); //不加引用可能编译失败
  t1.join(); // 需要在thread对象销毁之前决定线程是 join 还是deatch ,否则程序会异常终止
  arg.printData(100);                                                                                                                                                                                                             
  return 0;
}
传递一个类成员函数
int main(int argc, char** argv)
{
  ThreadArg  arg;
  std::thread t(&ThreadArg::printData, &arg,100);
  t.join();                                                                                                                                                                                                  
  return 0;
}
参数是unique_ptr
void func_ptr(std::unique_ptr<ThreadArg> ptr)
{
  ptr->setData(1000);

int main(int argc, char** argv)
{
  std::unique_ptr<ThreadArg> ptr{new ThreadArg};
  std::thread t(func_ptr, std::move(ptr));
  t.join();
  if (ptr)
  {
    ptr->printData(100);
  }
  return 0;
}
 

发布了78 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43778179/article/details/105056460