[C++11 并发编程] 02 - join

1. 等待线程完成

若不等待线程完成,我们就需要确保该线程访问的数据都是有效的,直到该线程完成为止。比如如下代码,线程函数持有局部变量的指针或引用,当函数退出时,线程尚未执行完成。

#include <thread>
#include <iostream>


// 线程持有局部变量的指针
struct func
{
	int *i;
	func(int *i_) : i(i_){
	
	}

	void operator()()
	{
		for (unsigned j = 0; j < 100000; ++j)
		{
			*i = j; // 访问非法地址
		}
	}
};

// 不等待线程执行完成就退出
void oops()
{
	int some_local_state = 0;
	func my_func(&some_local_state);
	std::thread my_thread(my_func);
	my_thread.detach();
}

int _tmain(int argc, _TCHAR* argv[])
{
	oops();

	return 0;
}

要避免这种情况,需要使用std::thread实例的join()来替换my_thread.detach()的调用,这样就可以保证在函数退出前,线程已经结束。对一个给定的线程,只能调用一次join(),一旦调用了join(),此std::thread对象不再是可连接的,如果调用其的joinable()将返回false。

2. 在异常环境下的等待

我们需要在线程对象被销毁前调用join或detach方法,如果要detach,通常在线程启动后就立即调用detach方法。如果打算等待该线程,就需要仔细的选择在哪个位置调用join。如果在线程开始之后,调用join之前发生了异常,则可能跳过对join的调用。

为了避免应用程序在引发异常的时候被终止,你需要异常时也调用join。

void do_something_in_current_thread()
{
	throw("error");
}

// 不等待线程执行完成就退出
void oops()
{
	int some_local_state = 0;
	func my_func(&some_local_state);
	std::thread my_thread(my_func);

	try
	{
		do_something_in_current_thread();
	}
	catch (const char *err_msg)
	{
		my_thread.join();
		throw;
	}
	
	my_thread.join();
}
try/catch块可以确保无论函数时正常退出还是异常退出,都调用了线程的join方法,但是try/catch块看起来很啰嗦,也容易导致作用于混乱,更简单的办法是使用RAII-Resource Acquisition Is Initialization并提供一个类,在析构函数中调用join():

class thread_guard
{
	std::thread& t;
public:
	explicit thread_guard(std::thread& t_) :
		t(t_)
	{
	}

	// 析构函数中检查线程是否还未被join,若没有,则调用
	~thread_guard()
	{
		if (t.joinable())
		{
			t.join();
		}
	}

	// 将拷贝后赋值运算符标记为=delete以避免编译器自动生成,复制或赋值这样一个对象可能很危险,因为它可能比它要结合的线程的作用域存在得更久。
	thread_guard(thread_guard const&) = delete;
	thread_guard& operator=(thread_guard const&) = delete;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值