C++20 std::jthread调用join失败报错,求正确停止线程的方法
如何正确停止std::jthread并避免join失败?
问题描述
使用C++20的std::jthread(apple-clang 14.0环境,依赖Nicolai Josuttis的实现),运行程序时在do_stuff()末尾调用thread.join()触发失败,程序输出错误:
Starting thread...
Max attempts exceeded.
libc++abi: terminating with uncaught exception of type std::__1::system_error: thread::join failed: Invalid argument
原代码如下:
#include <fmt/core.h> #include <thread> class ThreadedProcessor { private: int attempt{0}; const int max_attempts = 1; std::stop_source ssource; std::jthread thread; void do_stuff() { while (attempt < max_attempts) { ++attempt; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } fmt::print("Max attempts exceeded.\n"); ssource.request_stop(); thread.join(); } void start() { // was previously called process() thread = std::jthread([&, stoken = ssource.get_token()]() { fmt::print("Starting thread...\n"); while (!stoken.stop_requested()) { do_stuff(); } if (stoken.stop_requested()) { fmt::print("Stop requested. Stopping thread.\n"); } }); } public: ThreadedProcessor() { process(); } }; int main() { auto tp = ThreadedProcessor(); }
问题原因
- 非法的join调用:
do_stuff()在子线程内部执行,此时thread对象关联的就是当前运行的子线程——线程自身调用join()属于非法操作,直接触发系统错误。 - 默认构造jthread的状态问题:默认构造的
std::jthread处于非可结合状态(无关联执行线程),即便不在子线程内调用,直接对它执行join()也会报错。 - 线程启动笔误:构造函数里调用的
process()是不存在的函数,实际应调用start(),这会导致线程根本没被正确启动。
解决方案
关键修正点
- 移除子线程内的join调用:
std::jthread核心特性就是自动管理线程生命周期,当jthread对象销毁时,会自动请求停止并等待线程结束(自动执行join()),完全不需要手动在子线程内调用join()。 - 修正线程启动调用:把构造函数里的
process()改为start(),确保线程被正确启动。 - 利用jthread原生停止机制(可选优化):
jthread会自动创建stop_source,并将对应的stop_token传递给线程函数,无需手动维护std::stop_source,简化代码逻辑。
修正后的完整代码
#include <fmt/core.h> #include <thread> class ThreadedProcessor { private: int attempt{0}; const int max_attempts = 1; std::jthread thread; void do_stuff() { while (attempt < max_attempts) { ++attempt; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } fmt::print("Max attempts exceeded.\n"); } void start() { // 直接使用jthread自动传递的stop_token thread = std::jthread([this](std::stop_token stoken) { fmt::print("Starting thread...\n"); while (!stoken.stop_requested()) { do_stuff(); // 单次任务完成后主动检查停止请求,避免无限循环 if (stoken.stop_requested()) { break; } } fmt::print("Stop requested. Stopping thread.\n"); }); } public: ThreadedProcessor() { start(); // 修正笔误,调用正确的启动函数 } }; int main() { auto tp = ThreadedProcessor(); // 当tp销毁时,jthread会自动请求停止并join线程 }
额外说明
如果需要手动触发线程停止,可以给类添加一个公共方法:
void stop_processing() { if (thread.joinable()) { thread.request_stop(); } }
内容的提问来源于stack exchange,提问作者marital_weeping
相关产品推荐
相关产品推荐

