首页 > 代码库 > 转移线程的所有权

转移线程的所有权

线程不能被拷贝,但是可以转移。在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);
}



转移线程的所有权