[英]pthreads mutex vs semaphore
pthread 庫提供的信號量和互斥量有什么區別?
信號量有一個同步計數器,互斥量只是二進制的(真/假)。
信號量通常用作回答資源的多少元素正在使用的明確機制——例如,表示 n 個工作線程的對象可能使用信號量來計算有多少工作線程可用。
事實是,您可以通過互斥鎖同步的 INT 來表示信號量。
我將討論互斥量與二進制信號量。 您顯然使用互斥鎖來防止一個線程中的數據同時被另一個線程訪問。
(假設您剛剛調用了 lock() 並且在訪問數據的過程中。這意味着,您不希望任何其他線程(或同一線程代碼的另一個實例)訪問由相同的互斥鎖。也就是說,如果在不同的線程實例上執行相同的線程代碼,並且鎖定了鎖,那么 lock() 應該阻塞控制流。)
這適用於使用不同線程代碼的線程,該線程也訪問相同的數據並且也被相同的互斥鎖鎖定。
在這種情況下,您仍在訪問數據的過程中,並且您可能需要另外 15 秒才能到達互斥鎖解鎖(以便在互斥鎖中被阻塞的另一個線程將解鎖並允許控制訪問數據)。
您是否曾經允許另一個線程解鎖相同的互斥鎖,然后又允許已經在互斥鎖中等待(阻塞)的線程解鎖並訪問數據? (希望你明白我在這里說的話。)
根據商定的通用定義,
因此,如果您非常注重使用二進制信號量而不是互斥鎖,那么您應該在“范圍”鎖定和解鎖時非常小心,我的意思是,命中每個鎖的每個控制流都應該命中解鎖調用,並且不應該有任何“第一次解鎖”,而應該總是“第一次鎖定”。
廁所示例
互斥體:
是廁所的鑰匙。 一個人可以擁有鑰匙——占用廁所——當時。 完成后,此人將鑰匙交給(釋放)隊列中的下一個人。
“互斥鎖通常用於序列化對不能由多個線程同時執行的可重入代碼部分的訪問。互斥鎖對象只允許一個線程進入受控部分,迫使其他線程嘗試訪問該部分等到第一個線程從該部分退出。”
(互斥量實際上是值為 1 的信號量。)
信號:
是免費的相同馬桶鑰匙的數量。 例如,假設我們有四個帶有相同鎖和鑰匙的馬桶。 信號量計數 - 鑰匙的數量 - 一開始設置為 4(所有四個廁所都是免費的),然后隨着人們進來,計數值遞減。如果所有廁所都滿了,即。 沒有剩余的空閑鍵,信號量計數為 0。現在,當 eq. 一個人離開廁所,信號量增加到1(一個空閑鍵),並給隊列中的下一個人。
“信號量將共享資源的同時用戶數量限制為最大數量。線程可以請求訪問資源(遞減信號量),並可以發出信號表示它們已完成使用資源(遞增信號量)。”
互斥用於避免多個線程之間的競爭條件。
而信號量用作跨多個進程使用的同步元素。
互斥量不能用二進制信號量替換,因為一個進程等待信號量而另一個進程釋放信號量。 如果互斥,獲取和釋放都由相同的處理。
semaphore
和mutex
量的區別是機制和模式的區別。 區別在於它們的目的(意圖)和它們的工作方式(行為)。
mutex
、 barrier
、 pipeline
是並行編程模式。 Mutex
用於(打算)保護critical section
並確保mutual exclusion
。 Barrier
使代理(線程/進程)保持相互等待。
mutex
模式的特征(行為)之一是只有被允許的代理(進程或線程)才能進入臨界區,並且只有該代理才能自願退出。
有些情況下mutex
允許一個代理。 在某些情況下,它允許多個代理(多個讀者)而不允許其他一些代理(作者)。
的semaphore
是可使用的(打算)來實現不同的圖案的機構。 它是(行為)通常是一個標志(可能受互斥保護)。 (一個有趣的事實是mutex
模式甚至可以用來實現信號量)。
在流行文化中, semaphores
是內核提供的機制, mutexes
是用戶空間庫提供的。
請注意,對semaphores
和mutexes
存在誤解。 它說semaphores
用於synchronization
。 並且mutexes
擁有ownership
。 這是由於流行的操作系統書籍。 但事實是所有的互斥鎖、信號量和屏障都用於同步。 互斥的意圖不是ownership
而是mutual exclusion
。 這種誤解引起了流行的面試問題,詢問mutexes
和binary-semaphores
的區別。
概括,
意圖從設計的角度來看, mutex
更像是state-pattern
,其中由狀態選擇的算法可以改變狀態。 binary-semaphore
更像是strategy-pattern
,其中外部算法可以更改狀態並最終選擇運行的算法/策略。
信號量更多地用作標志,您真的不需要帶 RTOS / OS。 信號量可能會被其他線程意外或故意更改(比如由於錯誤的編碼)。 當您線程使用互斥鎖時,它擁有資源。 在資源被釋放之前,沒有其他線程可以訪問它。
互斥量只能應用於單個進程中的線程,而不能像信號量那樣在進程之間工作。
互斥體就像 S=1 的信號量。
您可以使用信號量控制並發訪問的數量,但使用互斥鎖一次只能有一個進程可以訪問它。
請參閱下面這兩個的實現:(所有功能都是原子的)
信號:
wait(S) {
while (S <= 0 )
; // busy wait
S--;
}
signal(S) {
S++;
}
互斥體:
acquire() {
while (!available)
; // busy wait
available = false;
}
release() {
available = true;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.