簡體   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