Eve*_*one 4 c++ multithreading lifetime
我有以下功能:
void threadProc(){
for (int i = 0; i < 5; ++i) {
std::cout << "\n thread #" << std::this_thread::get_id() << " says hi";
}
std::cout << "\n Finished executing thread #" << std::this_thread::get_id();
}
Run Code Online (Sandbox Code Playgroud)
我使用它的方式如下:
int main(){
try {
std::thread t1(threadProc);
t1.join();
std::thread t2(threadProc);
HANDLE handle = t2.native_handle();
WaitForSingleObject(handle, INFINITE);
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
std::cout << "\n thread t2 is joinable: " << std::boolalpha << t2.joinable() << "\n\n";
}
catch (std::exception& ex){
std::cout << "\n\n " << ex.what() << "\n\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是输出:
线程#21300说嗨
线程#21300说嗨
线程#21300说嗨
线程#21300说嗨
线程#21300说嗨
完成执行线程#21300
线程#2136说嗨
线程#2136说嗨
线程#2136说嗨
线程#2136说嗨
线程#2136说嗨
完成执行线程#2136
线程t2是可连接的:true
然后当try块超出范围时崩溃因为abort()被调用t2.
我的问题是,为什么t2仍然joinable()即使它的时候threadProc结束?为什么没有完成处理?
而且,我正在使用WaitForSingleObject以确保我等到t2完成处理.我还添加了5秒等待,以确保它花费时间来完成其处理.然而,有些事情仍未完成.
我知道我可以使用t2.join(),t2.detach()但我为什么要这样做?t2已完成处理(我认为).
编辑:我尝试了以下代码:
int main() {
try {
std::thread t1([]() {std::cout << "\n\n Hi from thread #" << std::this_thread::get_id(); });
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
catch (std::exception& ex) {
std::cout << "\n\n " << ex.what() << "\n\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
而且线程仍然可以连接.我抬头看了joinable参考文献,他们说:
已完成执行代码但尚未加入的线程仍被视为活动执行线程,因此可以连接.
所以这与此无关WaitForSingleObject.问题是为什么joinable()在完成执行后仍然会考虑一个线程?
我已经看到了这个问题,这让我感到困惑,甚至更多,因为它指出,当线程执行完毕后,它不是joinable()甚至称之前join()或detach().
joinable 并不意味着 still_running,joinable 只是意味着线程对象不是“空的”(作为默认构造或移动的结果)并且与真正的操作系统执行线程相关联。
如果线程为空,则意味着没有要加入的内容,因此,该线程不可“加入”。
如果线程不为空,您可以让当前线程等待它,因此它是“可加入的”。
问题是为什么线程在完成执行后仍被认为是joinable()?
因为你可能想编写join()的代码.如果t.joinable()在终止时自动变为假,那么就没有安全的方式来打电话t.join().你可以这样写:
if (t.joinable()) {
t.join();
}
Run Code Online (Sandbox Code Playgroud)
但是,如果线程在t.joinable()返回之后终止true,但在调用者能够完成t.join()调用之前,仍然会抛出异常.
让线程保持可连接直到它实际上是join()ed是更简单的行为来描述,并且编写正确使用它的代码更容易.