关于std::thread的join和detach的一些感悟
最近项目里大量用到了多线程,出了一些问题,经过一番研究后找到了问题所在,同时对多线程理解更深了一步,故写此博客分享一波。。。
将我遇到的问题简化为一下代码,示例:
#include <iostream> #include <thread> int main() { std::thread t([]() { std::string s = "123"; std::thread tt([&]() { std::cout << s << std::endl; }); tt.detach(); }); t.detach(); std::cin.get(); return 0; }
上面的代码执行错误,报 “引发了异常:读取访问权限冲突”。这是因为s已经析构了。对一个已经析构的对象进行操作,必然会出现问题。
程序执行到tt.detach()后会继续向下执行,然后会遇到 } ,会调用对象的析构函数。
解决方法:
1. tt.detach()换成tt.join(), join()会阻塞在那里,等待线程函数执行完。
2. 将捕获引用改为捕获值 [&] 改为 [=] 或者 [s]。
话说的这么简单,但是在一个项目里线程套线程,中间又可能夹杂着大量的代码,难免会忘记一些东西,所以我总结如下:
如果想用detach,则lambda表达式 的捕获列表应该尽量用值传递,或者用引用传递进来,拷贝一份用拷贝的值,总之不要用外面的值,(多此一举,直接捕获值多好)。
如果用join,则没有这么多的顾虑。。。