互斥鎖與號誌的差異:比較互斥與同步

互斥鎖用來保護臨界區段,讓同一時間只有一個執行緒能使用共享資源。鎖定的執行緒也必須由它自己解鎖。號誌是一個計數器,用來控制同時能使用有限資源的執行緒數量,也可用來從一個執行緒向另一個執行緒通知事件。互斥鎖是為了擁有與互斥,號誌則是為了計數與通知。

項目互斥鎖號誌
目的互斥。同一時間只有一個執行緒能進入臨界區段計數。限制對 N 個資源池的存取,或在執行緒之間通知事件
值鎖定中或未鎖定(二值)0 以上的整數計數(只有 0 或 1 的情形稱為二元號誌)
擁有者由鎖定的執行緒持有,也應由該執行緒解鎖沒有擁有者。任何執行緒都能發出 post 或 signal
操作鎖定與解鎖wait(P,減少)與 post(V,增加)
執行緒間的訊號不在設計考量內可以使用。例如生產者通知消費者
優先權反轉多半可用優先權繼承來避免通常不支援
主要用途保護清單或計數器等共享資料結構限制連線池、容量有限的生產者、消費者緩衝區、從中斷處理常式向工作任務通知
常見陷阱鎖定順序不一致造成的死結、忘記解鎖計數不吻合造成的訊號遺漏與死結

數值為具代表性的大致參考值,會因世代或產品而異。

適用於什麼情況

互斥鎖
多個執行緒會存取同一份資料,且同一時間只允許一個時。
號誌
想限制使用資源的執行緒數量,或想在發生某件事時喚醒執行緒時。

常見問題

互斥鎖與二元號誌相同嗎?

不相同。兩者都有兩種狀態,但互斥鎖有擁有者,必須由擁有者解鎖,且多半支援優先權繼承。號誌沒有擁有者,任何執行緒都能發出訊號。

什麼時候需要計數號誌?

想限制能使用資源的執行緒數量時,例如 N 個連線的連線池;或是在生產者、消費者緩衝區中,想計算可用元素數量時。

什麼是死結?

執行緒彼此永遠互相等待的狀態。例如執行緒 A 持有鎖 1 並等待鎖 2,而執行緒 B 持有鎖 2 並等待鎖 1。讓取得鎖的順序一致即可避免。

自旋鎖與互斥鎖有什麼不同?

自旋鎖以忙碌等待的方式等候,適合多核心上極短的等待。互斥鎖會讓等待的執行緒睡眠,適合較長的等待。

相關名詞的解說

互斥鎖(Mutex)
同一時間只有一個執行緒能持有的鎖。無法取得時讓執行緒休眠並讓出 CPU,鎖被釋放時由作業系統喚醒,是一般常見的實作。
號誌(Semaphore)
具有表示剩餘數量之計數器的同步機制。使用前減 1(若為 0 則等待),用完後加 1。用於管理可同時使用數量固定的資源。
自旋鎖(Spinlock)
以迴圈持續檢查鎖變數直到鎖被釋放來等待的鎖。等待時間短時很快,但等待期間仍持續佔用 CPU。
死結(Deadlock)
多個執行緒各自持有資源,並互相等待其他執行緒所持有的資源,使得誰都無法前進的狀態。可藉由全體統一取鎖順序來防止。

相關的比較