将t.join()移至try块内是否安全?——C++线程代码疑问
关于C++线程
join()位置的疑问 我在《C++ concurrency》一书中看到如下代码片段:
//callable whose defintion is not related to this question struct my_func; void f() { int some_local_state = 0; func my_func(some_local_state); std::thread t(my_func); try { do_something_in_current_thread(); //can we put/move the t.join() here? instead of having it at point #2 } catch (...) { t.join(); throw; } //author put the t.join() here why not inside try block t.join(); //#2 }
作者将t.join()放在try-catch块之后的#2处,而非try块内do_something_in_current_thread()调用之后。作为多线程初学者,我想了解这么做是否有技术原因或优势,仅针对该代码本身,不考虑jthread替代方案。
解答
两种写法都能保证线程一定会被join()(不会出现线程对象销毁时未完成join/detach导致程序终止的问题),但作者的写法有两个明显的优势:
职责划分更清晰:try块的核心作用是包裹可能抛出异常的
do_something_in_current_thread(),而t.join()作为线程资源的收尾清理动作,放在函数末尾的正常流程里,和线程对象t的创建形成“先初始化,最后收尾”的对称结构,代码逻辑更直观。避免冗余的分支重叠:如果把
t.join()放进try块内,虽然正常流程能正常执行,但异常分支里还是得写一遍t.join()——本质是重复代码。而作者的写法中,正常流程走#2的t.join(),异常流程走catch块内的t.join(),两者互不重叠,代码结构更规整,也符合“异常处理只负责异常场景下的补救”的设计思路。
从执行效率和功能正确性上,两种写法没有本质区别,核心差异在于代码的可读性和结构合理性。
内容的提问来源于stack exchange,提问作者user20562802
相关产品推荐
相关产品推荐

