POSIX threads(簡稱Pthreads)是在多核平台上進行並行編程的一套API。線程同步是並行編程中非常重要的通訊手段,其中最典型的應用就是用
Pthreads提供的鎖機制(lock)來對多個線程之間的共享臨界區(Critical Section)進行保護(另一種常用的同步機制是barrier)。
Pthreads提供了多種鎖機制:
- Mutex(互斥量):pthread_mutex_t
- Spin lock(自旋鎖): pthread_spin_t
- Condition Variable(條件變量): pthread_cond_t
- Read/Write lock(讀寫鎖):pthread_rwlock_t
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);
從實現原理上來講,Mutex屬於sleep-waiting類型的鎖。例如在一個雙核的機器上有兩個線程(線程A和線程B),它們分別運行在Core0和Core1上。假設線程A想要通過pthread_mutex_lock操作去得到一個臨界區的鎖,而此時這個鎖正被線程B所持有,那么線程A就會被阻塞,
Core0會在此時進行上下文切換(Context Switch)將線程A置於等待隊列中,此時Core0就可以運行其它的任務而不必進行忙等待。而Spin lock
則不然,它屬於busy-waiting類型的鎖,如果線程A是使用pthread_spin_lock操作去請求鎖,那么線程A就會一直在Core0上進行忙等待並不停的進行鎖請求,直到得到這個鎖為止。
自旋鎖(Spin lock)
自旋鎖與互斥鎖有點類似,只是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那里看是否該自旋鎖的保持者已經釋放了鎖,“自旋鎖”的作用
是為了解決某項資源的互斥使用。因為自旋鎖不會引起調用者睡眠,所以自旋鎖的效率遠高於互斥鎖。
自旋鎖的不足之處:
自旋鎖一直占用着CPU,他在未獲得鎖的情況下,一直運行(自旋),所以占用着CPU,如果不能在很短的時間內獲得鎖,這無疑會使CPU效率降低。
在用自旋鎖時有可能造成死鎖,當遞歸調用時有可能造成死鎖,調用有些其他函數也可能造成死鎖,如 copy_to_user()、copy_from_user()、kmalloc()等。
因此我們要慎重使用自旋鎖,自旋鎖只有在內核可搶占式或SMP的情況下才真正需要,在單CPU且不可搶占式的內核下,自旋鎖的操作為空操作。自旋鎖適用於鎖使用者保持鎖時間比較短的情況下。