std::thread/jthread是否会未执行传入函数便退出?join与stop_source场景
关于std::thread/std::jthread的join与执行保证
1. std::thread的join()行为
根据C++标准,std::thread的构造函数完成后,对应的OS线程已经处于可调度状态(可能已经在运行,也可能等待调度)。调用join()时,当前线程会阻塞,直到目标线程的入口函数完全执行完毕。不存在“OS线程未启动就调用join导致入口函数不执行”的情况——标准保证入口函数一定会被执行,join()会等待它完成。
你的示例代码中std::thread{foo}.join(),foo()必然会执行,这符合标准要求。
2. std::jthread的默认行为(无stop_token干预)
std::jthread的核心特性是自动join:当jthread对象被销毁时(比如临时对象std::jthread{foo}),会自动调用join(),行为和手动调用std::thread::join()一致。因此,在没有手动触发停止请求的情况下,传入的入口函数一定会被执行,你的示例中std::jthread{foo}的foo()必然运行,符合标准。
3. stop_source触发停止的特殊情况
你同事提到的“回调函数被调用前触发stop_source导致函数不执行”,是针对接受std::stop_token的入口函数的场景:
- 当你通过
std::stop_source提前发起停止请求(比如在jthread构造前就调用request_stop()),并将关联的stop_token传递给jthread时,jthread的内部包装器会先检查stop_token状态。 - 如果此时已经存在停止请求,包装器会直接返回,不会调用用户传入的入口函数(或者说,若函数内部先检查
stop_token,会直接返回,看起来像是核心逻辑未执行)。 - 但如果你的入口函数不接受
stop_token,jthread的包装器不会做停止检查,会直接执行你的函数,即使提前发起了停止请求,函数也会完整执行。
举个验证例子:
#include <thread> #include <iostream> // 接受stop_token的函数 void bar(std::stop_token st) { if (st.stop_requested()) { std::cout << "bar: 停止请求已在执行前发起\n"; return; } std::cout << "bar() 执行完毕\n"; } // 不接受stop_token的函数 void foo() { std::cout << "foo() 执行完毕\n"; } int main() { std::stop_source ss; ss.request_stop(); // 情况1:传入带stop_token的函数,核心逻辑可能不执行 std::jthread t1(ss.get_token(), bar); // 情况2:传入不带stop_token的函数,一定会执行 std::jthread t2(ss.get_token(), foo); }
运行结果可能为:
bar: 停止请求已在执行前发起 foo() 执行完毕
这符合C++20标准的规定——jthread的线程函数包装器会优先处理停止请求,仅当无停止请求时,才会正常执行用户的入口函数(或传递stop_token给用户函数)。
总结
- 对于
std::thread和不涉及stop_token的std::jthread:调用join()(或自动join)时,标准保证入口函数一定会执行,父线程会阻塞到子线程完成。 - 对于关联了已触发停止请求的
stop_token的std::jthread,且入口函数接受stop_token:存在入口函数核心逻辑未执行的可能(因为线程启动后先检查停止请求并返回)。
内容的提问来源于stack exchange,提问作者Yksisarvinen
相关产品推荐
相关产品推荐

