http://blog.csdn.net/kyokowl/article/details/6294341html
POSIX threads(簡稱Pthreads)是在多核平臺上進行並行編程的一套經常使用的API。線程同步(Thread Synchronization)是並行編程中很是重要的通信手段,其中最典型的應用就是用Pthreads提供的鎖機制(lock)來對多個線程之間共 享的臨界區(Critical Section)進行保護(另外一種經常使用的同步機制是barrier)。編程
Pthreads提供了多種鎖機制:
(1) Mutex(互斥量):pthreadmutex
(2) Spin lock(自旋鎖):pthreadspin
(3) Condition Variable(條件變量):pthreadcon
(4) Read/Write lock(讀寫鎖):pthreadrwlockide
Pthreads提供的Mutex鎖操做相關的API主要有:
pthread_mutex_lock (pthread_mutex_t mutex);
pthread_mutex_trylock (pthread_mutex_t mutex);
pthread_mutex_unlock (pthread_mutex_t *mutex);函數
Pthreads提供的與Spin Lock鎖操做相關的API主要有:
pthread_spin_lock (pthread_spinlock_t lock);
pthread_spin_trylock (pthread_spinlock_t lock);
pthread_spin_unlock (pthread_spinlock_t *lock);.net
從 實現原理上來說,Mutex屬於sleep-waiting類型的鎖。例如在一個雙核的機器上有兩個線程(線程A和線程B),它們分別運行在Core0和 Core1上。假設線程A想要經過pthread_mutex_lock操做去獲得一個臨界區的鎖,而此時這個鎖正被線程B所持有,那麼線程A就會被阻塞 (blocking),Core0 會在此時進行上下文切換(Context Switch)將線程A置於等待隊列中,此時Core0就能夠運行其餘的任務(例如另外一個線程C)而沒必要進行忙等待。而Spin lock則否則,它屬於busy-waiting類型的鎖,若是線程A是使用pthread_spin_lock操做去請求鎖,那麼線程A就會一直在 Core0上進行忙等待並不停的進行鎖請求,直到獲得這個鎖爲止。線程
自旋鎖(Spin lock)rest
自旋鎖與互斥鎖有點相似,只是自旋鎖不會引發調用者睡眠,若是自旋鎖已經被別的執行單元保持,調用者就一直循環在那裏看是 否該自旋鎖的保持者已經釋放了鎖,"自旋"一詞就是所以而得名。其做用是爲了解決某項資源的互斥使用。由於自旋鎖不會引發調用者睡眠,因此自旋鎖的效率遠 高於互斥鎖。雖然它的效率比互斥鎖高,可是它也有些不足之處:
一、自旋鎖一直佔用CPU,他在未得到鎖的狀況下,一直運行--自旋,因此佔用着CPU,若是不能在很短的時 間內得到鎖,這無疑會使CPU效率下降。
二、在用自旋鎖時有可能形成死鎖,當遞歸調用時有可能形成死鎖,調用有些其餘函數也可能形成死鎖,如 copy_to_user()、copy_from_user()、kmalloc()等。
所以咱們要慎重使用自旋鎖,自旋鎖只有在內核可搶佔式或SMP的狀況下才真正須要,在單CPU且不可搶佔式的內核下,自旋鎖的操做爲空操做。自旋鎖適用於鎖使用者保持鎖時間比較短的狀況下。
自旋鎖的用法以下:
首先定義:spinlock_t x;
而後初始化:spin_lock_init(spinlock_t *x); //自旋鎖在真正使用前必須先初始化
在2.6.11內核中將定義和初始化合併爲一個宏:DEFINE_SPINLOCK(x)code
得到自旋鎖:spin_lock(x); //只有在得到鎖的狀況下才返回,不然一直「自旋」
spin_trylock(x); //如當即得到鎖則返回真,不然當即返回假
釋放鎖:spin_unlock(x);htm
結合以上有如下代碼段:blog
spinlock_t lock; //定義一個自旋鎖 spin_lock_init(&lock); spin_lock(&lock); ....... //臨界區 spin_unlock(&lock); //釋放鎖 還有一些其餘用法:
spin_is_locked(x)
// 該宏用於判斷自旋鎖x是否已經被某執行單元保持(即被鎖),若是是, 返回真,不然返回假。
spin_unlock_wait(x)
// 該宏用於等待自旋鎖x變得沒有被任何執行單元保持,若是沒有任何執行單元保持該自旋鎖,該宏當即返回,否
//將循環 在那裏,直到該自旋鎖被保持者釋放。
spin_lock_irqsave(lock, flags)
// 該宏得到自旋鎖的同時把標誌寄存器的值保存到變量flags中並失效本地中//斷。至關於:spin_lock()+local_irq_save()
spin_unlock_irqrestore(lock, flags)
// 該宏釋放自旋鎖lock的同時,也恢復標誌寄存器的值爲變量flags保存的//值。它與spin_lock_irqsave配對使用。
//至關於:spin_unlock()+local_irq_restore()
spin_lock_irq(lock)
//該宏相似於spin_lock_irqsave,只是該宏不保存標誌寄存器的值。至關 //於:spin_lock()+local_irq_disable()
spin_unlock_irq(lock)
//該宏釋放自旋鎖lock的同時,也使能本地中斷。它與spin_lock_irq配對應用。至關於: spin_unlock()+local_irq+enable()
spin_lock_bh(lock)
// 該宏在獲得自旋鎖的同時失效本地軟中斷。至關於: //spin_lock()+local_bh_disable()
spin_unlock_bh(lock)
//該宏釋放自旋鎖lock的同時,也使能本地的軟中斷。它與spin_lock_bh配對//使用。至關於:spin_unlock()+local_bh_enable()
spin_trylock_irqsave(lock, flags)
//該宏若是得到自旋鎖lock,它也將保存標誌寄存器的值到變量flags中,而且失//效本地中斷,若是沒有得到鎖,它什麼也不作。所以若是可以當即 得到鎖,它等//同於spin_lock_irqsave,若是不能得到鎖,它等同於spin_trylock。若是該宏//得到自旋鎖lock,那須要 使用spin_unlock_irqrestore來釋放。
spin_trylock_irq(lock)//該宏相似於spin_trylock_irqsave,只是該宏不保存標誌寄存器。若是該宏得到自旋鎖lock,須要使用spin_unlock_irq來釋放。spin_trylock_bh(lock)// 該宏若是得到了自旋鎖,它也將失效本地軟中斷。若是得不到鎖,它什麼//也不作。所以,若是獲得了鎖,它等同於spin_lock_bh,若是得 不到鎖,它等同//於spin_trylock。若是該宏獲得了自旋鎖,須要使用spin_unlock_bh來釋放。spin_can_lock(lock)// 該宏用於判斷自旋鎖lock是否可以被鎖,它實際是spin_is_locked取反。//若是lock沒有被鎖,它返回真,不然,返回 假。該宏在2.6.11中第一次被定義,在//先前的內核中並無該宏。自旋鎖的得到和釋放有多種方法,要根據場合選擇,能夠去http://soft.yesky.com/os/lin/10/2303010_4.shtml看看,介紹了不少關於自旋鎖的使用知識。本文引用了不少上面的知識。