在缺乏專門硬體指令的狀況下,存在多種同步機制演算法: (但其實各自的假設) 現代的電腦硬體都有簡單且明確的指令可達到相同的效果,不用再顧慮上述演算法的 willingness vs. turn,換言之,這些軟體的同步演算法已無實用價值。 Edsger Dijkstra 提出 semaphore 概念時,被廣泛用於 CS 跟 signaling 這兩類問題。 隨著電腦硬體逐漸提供 atomic 指令後,mutex 或稱為 lock 的機制被列入作業系統的實作考量: 簡言之,要搶資源時用 mutex,要互相通知時用 semaphore。 先來看 semaphore 與 mutex 的差異,參照 Michael Barr 的文章 Mutexes and Semaphores Demystified: mutex 與 Semaphore 都用於確保 critical section (以下簡稱 CS) 的正確,讓多個執行單元運作並存取資源時,執行結果不會因為執行單元的時間先後的影響而導致錯誤。 mutex 與 semaphore 兩者設計來解決不同的問題。區分 mutex 與 binary semaphore: Mutex 與 semaphore 是經常被混用的觀念(尤其是 binary semaphore = mutex 這種理解),做為系統的開發者,勢必需要釐清其中的差異。 對於 mutex 來說,解鎖只能由上鎖的 thread 來完成,經常使用的情境是對於資源的保護 / 互斥。就像是對於一個房間,只存在一把鑰匙,拿到的人就可以進入房間,而其他的人必須排隊等待,直到那個人出來。 semaphore 可以由原本的 thread 或是另外一個 thread 解開,因此可以讓數個 producer 與數個 consumer 在計數器的基礎上進行合作。經常的使用情境是在兩個 thread 間的同步上,當 thread 進行至某個點時,去通知 thread B 可以繼續往下執行。 另一個 mutex 與 binary semaphore 的差異在於,mutex 的使用可能產生副作用: priority inversion。假設有優先權從高至低的三個 thread T1、T2、T3,其中 T1 和 T3 需要一個由 mutex 保護的資源: 為此, mutex 實作中需要採用一些機制來防止 priority inversion。但是,因為 semaphore 是為了不同 thread 間同步而存在,實作上就不必為此煩惱。 在 Linux kernel 中,一開始是只有 semaphore 這個 structure,直到 2.6.16 版當中才把 mutex 從 semaphore 中分離出來 (這點可以從 LDD3e* 看出來)。雖然 Mutex 與 Semaphore 兩者都是休眠鎖,但是 Linux kernel 在實作 Mutex 的時候,有用到一些加速的技巧,將上鎖分為3個步驟:演变
既生瑜,何生亮?
mutex 與 semaphore 的差別在於:
补充
Mutex 與 Semaphore 最大的差異
當持鎖的 thread 還在運行,而且沒有存在更高 priority 的 task 時,我們可以大膽假設,持鎖 thread 很快就會把 thread 釋放出來 (看看 code 就知道了),因此會使用一個特化的 MCS spinlock 等待鎖被釋放。特化的 MCS spinlock 可以在被 reschedule 的時候退出 MCS spinlock queue。當走到這步時,就會到 Slow path。参考链接