在 C 中,我有一個 std::vector 執行緒,每個執行緒都運行一個永遠運行的函式 [while(true)]。我將它們加入一個 for 回圈:
for (auto& thread : threads)
{
thread.join();
}
當程式完成時,我在其中一個執行緒的解構式中得到一個 std::terminate() 呼叫。我想我理解為什么會發生這種情況,除了第一個執行緒,其他連接呼叫沒有被呼叫。
加入這些執行緒的正確方法是什么?真的有必要加入他們嗎?(假設他們在正常情況下不應該加入)
uj5u.com熱心網友回復:
如果執行緒因為永遠不會退出而無法加入,那么您可以使用std::thread::detach(https://en.cppreference.com/w/cpp/thread/thread/detach)。無論哪種方式,在加入之前,您都應該始終檢查std::thread::joinable( https://en.cppreference.com/w/cpp/thread/thread/joinable )。
這std::terminate確實很可能是由于正在運行的執行緒被破壞并且在此之前沒有被分離或連接。但是請注意,在應用程式退出時分離的執行緒會發生什么是實作定義的。如果可能的話,您可能應該更改這些執行緒中的邏輯以允許優雅退出(std::jthread或者std::atomic可以幫助制作可停止的執行緒):
編輯:半完整的 C 17“正確”代碼:
std::atomic stop{false};
std::vector<std::thread> threads;
threads.emplace_back(std::thread{[&] { while (!stop.load()) { /* */ }}});
threads.emplace_back(std::thread{[&] { while (!stop.load()) { /* */ }}});
//...
stop.store(true);
for (auto& thread : threads)
{
if (thread.joinable())
{
thread.join();
}
}
半完整的 C 20“正確”代碼:
std::vector<std::jthread> threads;
threads.emplace_back(std::jthread{[] (std::stop_token stopToken) { while (!stopToken.stop_requested()) { /* */ }}});
threads.emplace_back(std::jthread{[] (std::stop_token stopToken) { while (!stopToken.stop_requested()) { /* */ }}});
C 20std::jthread允許std::stop_token接收信號的函式停止。解構式std::~jthread()首先通過令牌請求停止,然后加入,因此在上述設定中基本上不需要手動清理。不幸的是,只有 MSVC STL 并且libstdc 目前支持它,而 Clanglibc 不支持。std::thread但是,如果您想進行一些鍛煉,則很容易實作自己。
uj5u.com熱心網友回復:
加入這些執行緒的正確方法是什么?
你的方式很好,取決于你想要做什么。
真的有必要加入他們嗎?
是的。和不。
看,主要問題std::thread是您需要清理它們,否則它們會“做壞事”(TM),但加入它們只是清理它們的一種方式。另一種方法是簡單地將它們從您的實際執行緒中分離出來,如果您不想再控制它們(似乎是這種情況?)。
您需要問自己的事情是您的設定是否有意義,您會創建一大堆執行緒,這些執行緒不會干凈地結束,而是會被整個行程的死亡隨機中斷。他們應該做的作業會發生什么?如果他們將輸出寫入某處并且中途中斷,那么您、您的雇主和您的客戶對檔案損壞還滿意嗎?
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/447443.html
