47 C++ 多线程 ------ thread.detach() 的坑点

detach()函数的作用:

主线程不和子线程汇合了;

子线程原本关联的主线程,现在就不在和主线程关联了,这个子线程就会驻留在后台运行;

该子线程会被C++运行时库接管,当子线程执行完毕后,由运行时库(实际上是守护线程,这个要知道linux的一些相关进程线程的知识才懂,如果不懂,就大致理解为有人接管就可以了)清理该线程相关资源

detach()函数的作用的坑点在未验证前自己想:可能发生的问题

从上面的detach的作用,我们就能看到问题点。由于主线程 和 子线程分离了,那么传递参数的时候就要特别注意了。

如果从主线程传递的参数,不是值传递,而是指针,引用;;;

那么在主线程早于子线程完成的时候,子线程用的这个地址还存在吗?

如果不存在了,代码就有问题了

detach函数坑点的总结:

从上一节的代码例子中我们将普通类型值的传递,C++自带类(string)的值传递,自定义类的值传递,普通类型引用的传递,C++自带类(string)的引用传递,自定义类的值引用传递,普通类型值的ref(引用)传递,C++自带类(string)的ref(引用)传递,自定义类的ref(引用)传递,做了测试,发现如下规律:

尽量值传递,不要用引用。虽然在VS2017下,没有问题,但是还是不建议用,因为不知道在其他编辑器上有没有问题。

正常引用也会被 thread 拷贝一份,因此引用传递也不会改变 实参的值。

如果一定要用引用,从前面的例子来看,加上ref(T t)才是真的改变实参值的方法。

那么传递的如果是指针呢?--不行

通过代码在 join()下验证,发现,传递的指针在子线程和主线程的值都一样。

这意味着,在detach()下,从主线程new 出来的int空间,当主线程先执行完毕后,这块空间就被销毁了,如果这时候 子线程还在用,就会有问题。

class Teacher162 {
public:
	void funpoint(int *num) {
		cout << "子线程 id为 = " << this_thread::get_id() << "    funpoint num = " << num << " * num = " << *num << endl;
	}
};

void main() {
	Teacher162 tea;
	int *pint = new int(100);
	cout << "主线程 id为 = " << this_thread::get_id() << " pint = " << pint << " *pint = " << *pint << endl;
	thread mythread(&Teacher162::funpoint,tea, pint);
	mythread.join();
	//主线程 id为 = 11684 pint = 000001260FAE7730 *pint = 100
	//	子线程 id为 = 3172    funpoint num = 000001260FAE7730 * num = 100
}

如果存在参数存在类型转换,这个类型转换是在主线程完成的?还是子线程完成的?

若传递的参数类对象,避免隐式隐式转换。这个点的理解在于:在参数有隐式转换的时候

class Teacher162 {
public:
	void funpoint(int *num) {
		cout << "子线程 id为 = " << this_thread::get_id() << "    funpoint num = " << num << " * num = " << *num << endl;
	}

	void funstring(const string str) {
		for (int i= 0; i < 10;i++) {

		cout << "子线程 id为 = " << this_thread::get_id() << "    funstring str = " << str << " & str = " << &str << endl;
		}
	}
};


void main(){


//不要做隐式转换的,例如需要一个 string,但是我们传递的是 char[],不能直接传递,我们要转换一下
	Teacher162 tea;
	char sourcestr[] = "nihao";
	cout << "主线程 id为 = " << this_thread::get_id() << " sourcestr = " << sourcestr << " &sourcestr = " << &sourcestr << endl;
	//需要string,我们传递的是char[],那么一定存在一个从char[]到string的 类型转换了 ,
	//问题是:这个类型转换是在什么时候发生的呢?是在主线程还是里子线程?如果在子线程中,那么有没有可能还没有转的时候主线程就执行完毕了,你还转个啥?
	//实际中,确实是在子线程中转的。因此在detach下隐式类型转换
	//thread mythread(&Teacher162::funstring, tea, sourcestr);//不要有隐式的类型转换
	//fix方案,是在传递参数的地方弄一个临时变量,实验证明,临时变量是在的构造是在主线程完成的。
	thread mythread(&Teacher162::funstring, tea, new string(sourcestr));
	mythread.detach();


}	



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值