我很好奇 cpu 在等待互斥鎖的執行緒期間的行為。現在我可以想象兩種可能性:
- cpu 停留在當前執行緒上并檢查互斥鎖是否已連續解鎖。
- cpu 會暫時切換到另一個執行緒(或行程),然后切換回原始執行緒并臨時檢查。哪個是正確的或 stl 以另一種方式實作?
uj5u.com熱心網友回復:
通常,執行緒會嘗試獲取互斥鎖,如果不能(例如,因為另一個執行緒已經獲取了它),它將通知調度程式,調度程式將阻塞等待執行緒并切換到不同的執行緒,然后(稍后,當鎖被釋放時)調度程式將解除阻塞等待執行緒并再次給它 CPU 時間。
在單 CPU 系統上;這幾乎是必需的。在發現無法獲取鎖和執行任務切換(到可能釋放鎖的執行緒)之間花費的所有 CPU 時間(例如“旋轉”/再次輪詢鎖)都是浪費 CPU 時間,這將一事無成(因為在任務切換發生之前沒有其他執行緒可以釋放鎖)。
然而,對多 CPU 系統的研究(我隱約記得大約 20 年前 Sun 為 Solaris 做過也可能沒有做過)表明少量的“自旋”(希望執行緒在不同的 CPU 及時釋放鎖定)可能是有益的(通過避免任務切換的成本)。我的直覺是“阻塞前旋轉所花費的時間”應該大致等于任務切換的成本(或者,如果任務切換花費 123 微秒,那么在調度程式被告知阻塞之前旋轉 123 微秒可能是值得的你的執行緒);但這在很大程度上取決于場景(例如鎖的競爭程度等)。
uj5u.com熱心網友回復:
要理解這一點,您首先需要了解執行緒和 cpu 核心之間的區別。執行緒是一個抽象的東西,一種資料結構,用來表示一些要執行的操作序列。作業系統將執行緒分配給 cpu 核心,然后這些核心執行這些操作。作業系統(以及硬體)也可以隨時中斷此執行(盡管不是在單個指令的中間),保存此類執行緒的狀態,掛起它,并將其他一些執行緒分配給該內核。這也稱為背景關系切換。作業系統有時也會在所謂的系統呼叫上執行此操作(當程式呼叫某些作業系統的功能時,例如要求訪問磁盤、網路等)。這很重要,因為互斥體在后臺使用了一些系統呼叫。
那么當一個執行緒試圖訪問一個鎖定的互斥體時會發生什么?首先,不會進行定期檢查。雖然可能,但這會浪費 CPU 周期,而且任何嚴肅的作業系統都不太可能這樣做。實際發生的是每個互斥體內部都有一個關聯的佇列。當它被鎖定時,作業系統會將當前執行緒添加到該佇列中并將其掛起。之后,如果可用,作業系統會為這個 cpu 核心分配一些其他執行緒。
現在,如果互斥鎖被鎖定,那么實際上有一個執行緒鎖定了該互斥鎖。讓我們稱該執行緒為所有者。這個執行緒沒有掛起,它做了一些作業。當它完成它正在做的任何事情時,它必須解鎖互斥鎖(這也是一個系統呼叫),否則那些掛起的執行緒將永遠不會恢復。當這種情況(即解鎖)發生時,作業系統將查看關聯的佇列,并從中選擇一個執行緒(哪個是實作細節,通常是一些優先級佇列)。這個新選擇的執行緒將成為互斥鎖的新所有者,作業系統將恢復它,這意味著安排執行緒執行。調度,因為此時所有核心可能都處于忙碌狀態。
請注意,這是對該主題的簡要概述。還有很多其他的東西和優化在起作用,比如futex以及如何在沒有互斥鎖的情況下實際實作執行緒安全(或者更確切地說是內核安全)代碼(這些不是硬體功能,互斥鎖是在作業系統中實作的)。但這或多或少是這樣的。
uj5u.com熱心網友回復:
通常,
- 硬體執行緒(您的“CPU”)將被內核切換到運行不同的軟體執行緒,并且原始軟體執行緒將被擱置,直到它正在等待的互斥體發出信號。此時,內核將把它放在它尋求調度以在系統中的一個硬體執行緒上執行的一組軟體執行緒中。
您的選項 1 適用于 Microsoft 平臺上所謂的關鍵部分,更普遍的是spinlock。見pthread_spin_lock()。
您的選項 2 與通常發生的情況最相似。
uj5u.com熱心網友回復:
在 Microsoft 世界中,Mutex使用WaitForSingleObject()來等待,它被描述為
如果物件的狀態是無信號的,則呼叫執行緒進入等待狀態,直到物件發出信號或超時間隔過去。
現在您需要知道“等待狀態”是執行緒未處于活動狀態的狀態。我們稱之為“阻塞”,這與使用 CPU 時間的繁忙等待相反。
一開始,內核會立即將 CPU 分配給另一個執行緒,并且永遠不會將其回傳給您的執行緒,除非 Mutex 正在“發出信號”。所以它在等待期間真的會使用 0 個 CPU 周期。
當內核注意到 Mutex 已更改時,它可以“喚醒”執行緒,甚至可能提高其優先級,因為它一直在友好地等待。
cpu 停留在當前執行緒上并檢查互斥鎖是否已連續解鎖。
選擇要執行的執行緒的不是 CPU。Windows 的執行緒調度程式將選擇一個被執行的執行緒。
如果 Mutex 可以以這種方式阻塞 CPU,那么您只需要 8 或 12 個 Mutex 就可以使系統完全變磚。
cpu 將切換到另一個執行緒(或行程)片刻 [...]
幾乎。會有一個定時器中斷。中斷將由 Windows 內核的中斷服務例程處理。屆時,內核可以決定接下來將執行哪個執行緒。
[...] 并切換回原始執行緒并臨時檢查。
不,因為 Mutex 是一個內核物件,內核已經知道除非 Mutex 已經被通知,否則讓執行緒再次檢查是沒有用的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/442901.html
