繁体   English   中英

C ++线程在完成执行后仍然是`joinable()`吗?

[英]C++ thread still `joinable()` after it finishes execution?

我有以下功能:

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();
}

我使用它的方式如下:

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;
}

这是输出:

线程#21300说嗨

线程#21300说嗨

线程#21300说嗨

线程#21300说嗨

线程#21300说嗨

完成执行线程#21300

线程#2136说嗨

线程#2136说嗨

线程#2136说嗨

线程#2136说嗨

线程#2136说嗨

完成执行线程#2136

线程t2是可连接的:true

然后当try块超出范围时崩溃,因为在t2调用了abort()

我的问题是,为什么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;
}

而且线程仍然可以连接。 我查看了joinable参考文献,他们说:

已完成执行代码但尚未加入的线程仍被视为活动执行线程,因此可以连接。

所以这与WaitForSingleObject无关。 问题是为什么线程在完成执行后仍被认为是joinable()

我已经看到这个问题让我更加困惑,因为它表明当线程完成执行时,即使在调用join()detach()之前它也不是joinable() detach()

问题是为什么线程在完成执行后仍被认为是joinable()?

因为你可能想编写join()的代码。 如果t.joinable()在终止时自动变为false,那么就没有安全的方法来调用t.join() 你可以这样写:

if (t.joinable()) {
    t.join();
}

但是,如果线程在t.joinable()返回true之后终止,但在调用者能够完成t.join()调用之前终止,则仍会抛出异常。

让线程保持可连接直到它实际上是join()ed是更简单的行为来描述,并且编写正确使用它的代码更容易。

joinable并不意味着still_running ,可连接只是意味着线程对象是不是“空”(如缺省结构或移动的结果),并与执行的真实OS线程相关联。

如果线程为空,则意味着没有任何东西可以连接,因此,线程不是“可连接的”。

如果线程不为空​​,则可以使当前线程等待它,因此它是“可连接的”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM