线程不能被拷贝,但是可以转移。在C++中,std::ifstream不能拷贝,但是可以转移(moveable),std::thread一样。
void some_function(); void some_other_funciton(); std::thread t1(some_function);//创建线程t1,运行some_function std::thread t2=std::move(t1);//创建t2,t1所有权交给t2,这时t1不在和运行线程相关 t1=std::thread(some_other_funciton);//创建新线程,和t1关联。 std::thread t3; t3=std::move(t2);//控制权交给t3 t1=std::move(t3);//控制权交给t1,这时t1运行的线程就会结束
函数返回值为线程
std::thread f() { void some_function(); return std::thread(some_function); } std::thread g() { void some_other_function(int); std::thread t(some_other_function,42); return t; }
如果函数的参数为线程,那么它只能接收值传递。
void f(std::thread t) { void some_funtion(); f(std::thread(some_function)); std::thread t(some_function); f(std::move(t)); }
对象控制权的转移的一个用法是用thread_guard对象来管理thread对象的声明周期(RAII)。在创建thread_guard对象时拿到thread对象的控制权,在其析构函数调用join等待线程。thread对象不允许拷贝和复制,所以只有thread_guard有它的控制权,在thread_guard对象销毁时,会等待线程的结束。用一个类scoped_thread来表示:
class scoped_thread { std::thread t; public: explicit scoped_thread(std::thread t_) t(std::move(t_) { if(!t.joinable()) throw std::logic_error("No thread"); } ~scoped_thread() { //析构函数调用join,等待线程结束 t.join(); } //禁用下面两个函数 scoped_thread(scoped_thread const&)=delete; scoped_thread * operator=(scoped_thread const &)=delete; }; struct func; void f() { int some_local_state; //直接传递了新创建的线程,没有命名变量 scoped_thread t(std::thread(func(some_local_state))); do_something_in_current_thread(); }
线程控制权的转移使得可以使用线程对象容器。下面代码表示创建多个线程之后等待它们结束。
void do_work(unsigned id); void f() { std::vector<std::thread> threads; for(unsigned i=0;i<20;++i) { threads.push_back(std::thread(do_work,i)); } //在每一个线程上调用join std::for_each(threads.begin(),threads.end(),std::mem_fn(&std::thread::join); }
时间: 2024-11-08 19:31:15