執行緒同步相關術語總結
對於初次接觸執行緒同步的前端來說,總是對互斥鎖、條件變數、訊號量等術語傻傻分不清楚,這裡根據自己的理解簡單做下總結,如有疏漏之處,歡迎大家批評指正。
互斥鎖
在多執行緒環境中往往存在因某一資源被同時訪問導致該資源不一致的問題,互斥鎖
通過排它性,即同時只允許一個訪問者對其進行訪問來保證資源的有效同步,但它無法限制執行緒對該資源的訪問順序,因此執行緒對資源的訪問也是無序的。
自旋鎖
在互斥鎖
中,如果執行緒 A 在請求鎖的時候發現該鎖已被執行緒 B 霸佔,那麼此時執行緒 A 便會進入休眠狀態,直到鎖被執行緒 B 釋放後被系統喚醒。但在自旋鎖
中,執行緒 A 在發現鎖被霸佔時並不進入休眠,而是一直迴圈檢視鎖的持有者是否已經釋放了該鎖。初看起來,這種霸佔CPU資源的做法極其低效,但與互斥鎖
- 實現簡單:只需死迴圈檢測鎖狀態即可,沒有
互斥鎖
休眠、喚醒所涉及的一系列上下文切換、CPU搶佔等各種複雜流程。 - 高效:正是由於實現極其簡單,所以它在一些情況下極其高效。
當然,上面的高效也是有條件的,由於它佔用CPU資源,所以它主要適用於以下場景:
- 臨界區持鎖時間較短且CPU資源不緊張。
- 多用於多核環境。
遞迴鎖
遞迴鎖
又叫可重入鎖
,與 互斥鎖
的主要區別是在同一個執行緒內可以多次獲得鎖資源,別的執行緒必須等待該執行緒釋放相應次數的鎖才能獲得,其主要目的是為了解決同一程序內的死鎖問題,但在不同的執行緒中,它與互斥鎖
並沒有什麼區別。
讀寫鎖
上面介紹的互斥鎖
、自旋鎖
、遞迴鎖
都屬於排它鎖,即一個執行緒獲得鎖資源後,其他執行緒必須等待直到該鎖被釋放。但在某些讀多寫少的情況下,這樣的機制難免有些低效,因此讀寫鎖
就是為解決這樣的問題而誕生的。讀寫鎖分讀鎖和寫鎖,其特點如下:
- 讀鎖:如果執行緒 A 獲得了讀鎖,執行緒 B 可以獲得讀鎖,但不可以獲得寫鎖。
- 寫鎖:如果執行緒 A 獲得了寫鎖,執行緒 B 即不可以獲得讀鎖,也不可以獲得寫鎖。
- 寫鎖優先:如果執行緒 A 申請獲得寫鎖,執行緒 B 申請獲得讀鎖,優先給執行緒 A 分配寫鎖。
條件變數
條件變數
主要適用於一個執行緒需要等待某個共享資源滿足某個條件後進行一系列同步操作的場景。它主要包含:
- 等待某個條件成立的等待執行緒。
- 滿足某個條件成立的訊號傳送執行緒。
它一般與互斥鎖
配合使用(主要用來保護共享資源),在等待執行緒中,如果條件不成立,該執行緒會自動阻塞,並釋放掉等待狀態改變的互斥鎖,如果訊號傳送執行緒改變了條件,它傳送訊號給關聯的條件變數,並喚醒等待執行緒,等待執行緒重新獲得互斥鎖,重新評估條件。
訊號量
訊號量
主要適用於一個執行緒需要等待另外一個個執行緒完成一些操作後再繼續執行自己操作的場景,它與上面各種鎖的最大區別是:
- 鎖要解決的是共享資源的同步問題,而
訊號量
要解決的是執行緒之間任務同步問題。 - 鎖必須在同一程序進行加鎖和解鎖操作,而
訊號量
可以通過一個執行緒中得到,在另一個執行緒中釋放。
認真回味下我們會發現訊號量
要解決的問題也可以使用條件變數
來處理,相對於訊號量
,條件變數
主要有以下不足:
條件變數
需要藉助全域性共享變數以及互斥鎖
來達到狀態的檢測。條件變數
適用於多執行緒環境,無法適用於多程序環境。
屏障
屏障
是一種協調多個執行緒進行工作,即允許某個執行緒等待直到所有的合作執行緒達到某一個條件,然後從該條件下繼續執行的同步機制。
總結
本文對執行緒同步中所涉及到的術語的特點及適用場景進行了簡單的總結,如果你在閱讀過程中發現任何錯誤,歡迎留言指正,我們一起學習一起進步。^ _ ^