2.3转移线程的所有权(C++并发编程实战)

C++标准库中很多资源占有(resource-owning)类型,比如std::ifstream,std::unique_ptr还有std::thread都可以移动,但不可以拷贝

std::thread支持移动,这意味着线程的所有权可以在函数外移动,就如下面程序一样:

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;
}

前面写了个thread_guard类所持有的线程是引用,移动操作就可以避免不必要的麻烦。当某个对象转移了线程的所有权后,它就不能对线程进行加入或分离。如下定义了scoped_thread类,支持移动操作:


class scoped_thread
{
	std::thread t;
public:
	explicit scoped_thread(std::thread t_):			//1
		t(std::move(t_))			
	{
			if(!t.joinable())						//2
				throw std::logic_error("No thread");
	}
	
	~scoped_thread()
	{
		t.join();								//3
	}
				
	scoped_thread(const scoped_thread&) = delete;
	scoped_thread& operator=(const scoped_thread&) = delete;
};

struct func;

void f()
{
	int some_local_state;
	scoped_thread t(std::thread(func(some_local_state)));		//4
	do_something_in_current_thread();
}

这里新线程直接传递匿名对象到scoped_thread中(4),相当于移动操作。当主线程到达f()函数的末尾的时候,scoped_thread对象将调用析构函数(3),这里在构造函数中检查线程是否可以加入,不可以加入就抛异常。

std::thread对象的容器,如果这个容器是移动敏感的(比如vector),那么移动操作同样适用于这些容器。如下就是用于容器的量产一些线程,并且等待它们结束:

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)); //产生线程
	}
	std::for_each(threads.begin(),threads.end(),
					std::mem_fn(&std::thread::join)); //对每个线程调用join
}

将std::thread放入std::vector是向线程自动化管理迈出的第一步:并非为这些线程创建了独立的变量,并且将它们加入,可以把它们作为一个组。创建一组线程(数量在运行时确定),可使的这一步迈得更大,而非像上述那样创建固定数量的线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值