行程同步與臨界區間問題

自旋鎖(spinlock)

自旋鎖是最簡單的真實鎖:一把以忙碌等待為等待策略的互斥鎖。一條發現鎖被佔走的執行緒不會去睡,而是在一個緊湊迴圈裡自旋,反覆嘗試搶到鎖,直到成功為止。名字就說明了一切——你等待的期間,你的執行緒一直在旋轉。它正是把測試並設定或比較並交換迴圈包裝成可重複使用之鎖的、直接而實用的化身。

它的魅力在於:當爭用短暫時很快。由於等待者從不睡覺,就沒有「進核心去阻塞」與「再喚醒」這兩次環境切換的成本;持有者一釋放鎖,自旋的執行緒幾乎立刻就搶到。這讓自旋鎖很適合在多處理器機器上保護非常短的臨界區間——此時持有者確實正在另一顆核心上執行,幾條指令內就會釋放鎖。這正是作業系統核心內部的情形:許多資料結構由只持有寥寥幾條指令的自旋鎖守護。

另一面是,自旋鎖只在特定條件下才恰當,誤用則浪費甚至釀災。若臨界區間很長,每個等待者都會在那整段時間裡燒掉一整顆 CPU 核心、什麼也沒做——純粹浪費。在單處理器上它幾乎總是錯的:自旋的等待者阻止了持有者被排程去釋放鎖。而且經典的自旋鎖通常不保證有限等待,所以在高度爭用下,某一條執行緒可能一再被別人搶先。還有一條關鍵的核心規則:執行緒在持有自旋鎖時絕不可睡眠或被先佔,否則任何為它自旋的人都會浪費掉巨量時間;核心往往在自旋鎖短暫的生命期內關閉先佔(有時連中斷一起關)。「自旋鎖還是阻塞鎖」的抉擇,最終歸結為一句:這次等待會不會短於睡眠的成本?

核心要更新一個共用串列,其修改約需 20 條指令。它用自旋鎖:等待中的 CPU 為那短短幾奈秒自旋,而不去付「睡眠再喚醒」那大得多的代價。若同一個串列要花上幾毫秒才更新得完,那就該改用阻塞鎖才對。

自旋鎖 = 互斥鎖 + 忙碌等待。適合多核心上的短等待;不適合長等待或單處理器。

持有自旋鎖時絕不要睡眠或做緩慢的工作——這期間每個等待者都在燒一顆核心。在單一 CPU 上,為一個還沒輪到執行的持有者自旋,可能讓系統卡死。

又称
spin lockbusy-wait lock旋轉鎖