我是 C 多執行緒編程的新手,join()在看書時遇到了一些關于函式的困難:
呼叫 join() 的行為也會清除與執行緒關聯的所有存盤,因此 std::thread 物件不再與現在完成的執行緒關聯;它不與任何執行緒相關聯。這意味著您只能為給定執行緒呼叫一次 join() ;一旦你呼叫了 join(),std::thread 物件就不再是可連接的,并且 joinable() 將回傳 false。
“與執行緒關聯的存盤”具體是什么意思,為什么在呼叫時清理與執行緒關聯的存盤join()?誰能解釋一下這背后的原理?
uj5u.com熱心網友回復:
“與執行緒關聯的存盤”具體是什么意思,為什么在呼叫join()時要清理與執行緒關聯的存盤?誰能解釋一下這背后的原理?
當執行緒終止時,作業系統將其回傳狀態保存在內核特定資料結構的條目中。如果另一個執行緒呼叫join()終止的可連接執行緒,則該條目將被洗掉。但是,如果您不呼叫join()可連接執行緒,則會創建僵尸執行緒。換句話說,僵尸執行緒,是一種已經被終止的執行緒,但內核中仍然存在關于其狀態的條目。
考慮到每個僵尸執行緒都會消耗一些系統資源,如果累積了很多僵尸執行緒,將無法再創建新執行緒。
uj5u.com熱心網友回復:
與其他答案一樣,執行緒存盤與執行緒堆疊無關。當執行緒終止/結束時,所有執行緒資源都被釋放,除了作業系統內核結構中的一個資源,它保持執行緒退出狀態和作業系統使用的其他可能資料。加入只是洗掉該資料,作業系統永遠忘記該執行緒,進一步訪問該執行緒是未定義的行為,例如可能導致不可預知的加入新創建的執行緒。
uj5u.com熱心網友回復:
“與執行緒關聯的存盤”具體是什么意思。
大多數情況下,它意味著執行緒的呼叫堆疊。可能有幾兆位元組,但它們并不容易準確地找出分配了多少空間,或者提供任何明確定義的方法來更改它。請參閱如何使用 C 11 std::thread 設定堆疊大小
編輯:
我最初的答案(上圖)寫得很倉促,未能回答主要問題。我當時在想的是,清理執行緒時必須釋放的最大記憶體塊是執行緒的堆疊。
為什么不能多次呼叫 std::thread.join() ......?
因為這就是 C 標準庫的設計方式。在大多數作業系統中,創建新執行緒的系統呼叫必須由破壞它的系統呼叫來平衡,C 標準庫的設計者決定,對于任何thread未分離的系統呼叫,第二個系統呼叫應該發生在唯一的join()電話。
執行緒結束時必須釋放的資源通常有兩部分;“用戶空間”部分(即應用程式控制的內容)和“內核空間”部分
用戶空間部分主要由執行緒的呼叫堆疊組成。它通常是行程的虛擬地址空間中幾兆位元組的連續塊。它的分配方式取決于作業系統。在 Windows 中,執行緒堆疊由CreateThread(...)WinAPI 呼叫分配,并在執行緒本身呼叫時被釋放ExitThread(...)——這始終是任何 Windows 執行緒在終止之前所做的最后一件事。在 Linux 中,應用程式負責在創建新執行緒之前分配堆疊,并且在不再需要之后釋放堆疊。
用戶空間部分主要由執行緒的呼叫堆疊組成,但也有std::thread物件本身。分配和釋放執行緒物件的方式和時間與分配和釋放任何其他 C 物件的方式完全相同。
內核空間部分相對較小:它是內核記憶體中某處保存執行緒狀態(例如,“正在運行”、“可運行”、“等待...”、“死機”)的記錄,它保存著執行緒的背景關系。背景關系是每次執行緒被搶占時獲取的所有 CPU 暫存器的快照,然后在需要讓執行緒再次運行時加載回 CPU 暫存器。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/513378.html
下一篇:如果std::reference_wrapper沒有operator =,std::reference_wrapper<int>如何使用operator =?
