自旋鎖

1. 定義

一個自旋鎖是一個互斥設備,它只能有兩個值:“鎖定”和“解鎖”。如果鎖可用,則“鎖定”位被設置,而代碼繼續進入臨界區;相反,如果鎖被其他人獲得,則代碼進入忙循環並重複檢查這個鎖,直到該鎖可用爲止。這個循環爲“自旋”

2. 實現

             "\n1:\t"  
             lock " ; decb %0\n\t"  
             "jns 3f\n"  
             "2:\t"  
             "rep;nop\n\t"  
             "cmpb $0,%0\n\t"  
             "jle 2b\n\t"  
             "jmp 1b\n"  
             "3:\n\t" 

    第2行:lock>slock自減一,前面的lock保證原子操作

    第3行:如果lock>slock爲非負數,跳轉到3,獲得鎖

    第5行:lock->slock爲負數,鎖 被其他線程搶佔,等待

    第6行:將lock->slock和0比較

    第7行:判斷lock->slock是否小於等於0,如果判斷爲真,跳轉到2,繼續等待

    第8行:此時lock->slock已經大於0,跳轉到1搶佔鎖

3. 各平臺區別

自旋鎖是爲了多CPU而設計的,但單CPU搶佔內核時也類似於SMP。但各種情況還有一些差別,下面分類討論。

I. 單CPU非搶佔:自旋鎖空操作,完全剔除內核

II.單CPU搶佔:禁止CPU搶佔,無自旋鎖

III.多CPU非搶佔:自旋鎖。

IV.多CPU搶佔:禁止CPU搶佔,有自旋鎖。

問 :    在單CPU非搶佔中,爲什麼自旋鎖會實現爲空操作?

多線程之間共享數據,無自旋鎖會引起併發訪問嗎?

答 :    如果非搶佔單CPU進入某個鎖的自旋狀態,則會永遠自旋下去。(這句話要好好理解)

如果多線程在訪問共享數據的時候不休眠或者主動放棄CPU(schedule),不會引起併發訪問。因爲沒有進行進行線程切換,另外一個線程不會訪問此共享數據。這裏要說一下中斷的時候,如果中斷和此線程共享數據,要先禁用中斷,才能防止併發訪問。

4. 自旋鎖函數

I. spin_trylock(spinlock_t *lock)

在使用此函數的時候一定要注意檢查返回值,如果返回失敗,而又去修改共享數據,還是會引起競爭。相當於沒有獲取到鎖,破門而入。

II.spin_lock_irqsave(spinlock_t *lock, unsigned long flags) 和spin_lock_bh(spinlock_t *lock)

進程上下文與下半部或中斷共享數據。進程上下文會被softirq 或irq中斷,如果沒有禁用下半部或中斷,在此進程上下文獲得鎖的情況下,此進程被中斷,而中斷又去取鎖,會引起死鎖

 


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