自旋鎖(網絡博客等學習和整理)

時間:2014.06.17

地點:基地

-----------------------------------------------------------------------------------

一、簡述

   自旋鎖(spinlock)是爲防止多處理器併發而引入的一種鎖,在內核中大量應用於中斷處理。

-----------------------------------------------------------------------------------

二、自旋鎖的概念

   和互斥鎖類似,也是爲實現保護共享資源而提出的一種鎖機制,都是爲了解決對某項資源的互斥使用。無論是互斥鎖也好還是自旋鎖也好,在任何時刻,最多隻能有一個保存者,即任何時刻頂多只能有一個執行單元可以獲得鎖

-----------------------------------------------------------------------------------

三、自旋鎖與互斥鎖的區別

  互斥鎖和自旋鎖的區別主要在於調度機制的區別:對於互斥鎖,如果資源已經被佔用,資源申請只能進入睡眠狀態,但是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保存,調用者就一直循環在那裏看是否該自旋鎖的保存着已經釋放了鎖,自選一詞由此得名,打不開鎖,就一直在那自我旋轉試圖直到打開。

-----------------------------------------------------------------------------------

四、自旋鎖原理和應用場合

    和互斥鎖一樣,一個執行單元如果想要訪問被自旋鎖保護的共享資源,必須先得到所,在訪問完共享資源後,必須釋放鎖。若在獲得自旋鎖時,沒有任何執行單元保持該鎖,那麼就立刻得到該鎖,反之,若果在獲取自旋鎖時該鎖已經有保持着了,那麼獲得該鎖操作將自旋在那裏,直到自旋鎖的保持着釋放了鎖。

4.1自旋鎖存在的問題

      試圖遞歸地獲得自旋鎖必然會引起死鎖,在遞歸程序的持有實例在第二個實例循環,以試圖獲得相同的自旋鎖時,但此時自旋鎖又未被釋放,在遞歸程序中使用自旋鎖應遵守以下策略:遞歸程序絕不能在持有自旋鎖時調用它自己,也決不能在遞歸調用時試圖獲得相同的自旋鎖,此外如果一個進程已經將資源鎖定,那麼,即使其它申請這個資源的進程不停地瘋狂自旋也無法獲得資源,從而進入死循環。因此,如果不加限制,由於新的額資源申請者一直在循環等待,因此自旋鎖在鎖定時如果不成功它不會睡眠,而是持續嘗試,這樣,特別是在單CPU時,自旋鎖的這種持續旋轉會讓其他進程動不了,因此,一般在實現自旋鎖時,會有一個參數限定最多持續嘗試的次數,超出次數後,自旋鎖放棄當前的時間片等待下一次機會

4.2應用場景

        由上可知,自旋鎖比較適用於鎖的使用者保持鎖時間比較短的情況。也正是由於自旋鎖的使用者一般保持鎖時間非常短,因此選擇自旋而不是睡眠非常必要,自旋鎖的效率也遠高於互斥鎖。信號量和讀寫信號量適合於保持時間較長的情況,它們會導致調用者睡眠,因此只能在進程上下文使用,使用信號量保護該共享資源非常合適,如果對共享資源的訪問時間非常短,自旋鎖也可以。但若被保護的共資源需要再中斷上下文訪問(包括底半部即中斷處理句柄和頂半部即軟中斷),就必須使用自旋鎖。自旋鎖保持期間是搶佔失效的,而信號量和讀寫信號量保持期間是可以被搶佔的。自旋鎖只有在內核可搶佔或SMP(多處理器)的情況下才真正需要,在單CPU且不可搶佔的內核下,自旋鎖的所有操作都是空操作。

4.3細節

          在單處理機環境中可以使用硬件提供的swap指令或test_and_set指令實現進程互斥(swap指令用於交換兩個內存單元的內容,test_and_set指令用於取出內存某一單元位的值,然後再給該單元(位)賦一次新值,這些指令涉及對同一存儲單元的兩次或兩次以上的操作,這些操作將在幾個指令週期內完成,但由於中斷只能發生在兩條機器指令之間,而同一指令內的多個指令週期不可中斷,從而保證swap指令或test_and_set指令的執行不會交叉進行。但在多處理機環境中情況有所不同,例如test_and_set指令包括“取”、“送”兩個指令週期,兩個CPU執行test_and_set(lock)可能發生指令週期上的交叉,假如lock初始爲0, CPU1和CPU2可能分別執行完前一個指令週期並通過檢測(均爲0),然後分別執行後一個指令週期將lock設置爲1,結果都取回0作爲判斷臨界區空閒的依據,從而不能實現互斥。


  爲在多CPU環境中利用test_and_set指令實現進程互斥,硬件需要提供進一步的支持,以保證test_and_set指令執行的原子性. 這種支持目前多以“鎖總線”(bus locking)的形式提供的,由於test_and_set指令對內存的兩次操作都需要經過總線,在執行test_and_set指令之前鎖住總線,在執行test_and_set指令後開放總線,即可保證test_and_set指令執行的原子性。自旋鎖是一種對多處理器相當有效的機制,而在單處理器非搶佔式的系統中基本上沒有作用。自旋鎖在SMP系統中應用得相當普遍。在許多SMP系統中,允許多個處理機同時執行目態程序,而一次只允許一個處理機執行操作系統代碼,利用一個自旋鎖可以很容易實現這種控制.一次只允許一個CPU執行核心代碼併發性不夠高,若期望核心程序在多CPU之間的並行執行,將核心分爲若干相對獨立的部分,不同的CPU可以同時進入和執行核心事實上,自旋鎖的初衷就是:在短期間內進行輕量級的鎖定。一個被爭用的自旋鎖使得請求它的線程在等待鎖重新可用的期間進行自旋(特別浪費處理器時間),所以自旋鎖不應該被持有時間過長。如果需要長時間鎖定的話, 最好使用信號量。1自旋鎖實際上是忙等鎖。

  當鎖不可用時,CPU一直循環執行“測試並設置”該鎖直到可用而取得該鎖,CPU在等待自旋鎖時不做任何有用的工作,僅僅是等待(自旋鎖在自旋時此時CPU是一直空閒的),因此,只有在佔用鎖的時間極短的情況下,使用自旋鎖纔是合理的。當臨界區很大或有共享設備的時候,需要較長時間佔用鎖,使用自旋鎖會降低系統的性能。自旋鎖可能導致系統死鎖引發這個問題最常見的情況是遞歸使用一個自旋鎖,即如果一個已經擁有某個自旋鎖的CPU 想第二次獲得這個自旋鎖,則該CPU 將死鎖。此外,如果進程獲得自旋鎖之後再阻塞,也有可能導致死鎖的發生。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章