使用者態自旋鎖、讀寫自旋鎖及互斥鎖
1、自旋鎖
自旋鎖最多可能被一個可執行執行緒所持有。一個被徵用的自旋鎖使得請求它的執行緒在等待鎖重新可用時自旋(特別浪費處理器時間)。所以自旋鎖不應該被長時間持有。
自旋鎖是不可遞迴的!
(1)自旋鎖相關函式
使用者態的自旋鎖相關函式包含在標頭檔案<pthread.h>中。
相關函式:
int pthread_spin_destroy(pthread_spinlock_t *lock);
銷燬自旋鎖lock,並且回收被鎖lock使用的任何資源。
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
分配使用自旋鎖lock所需要的資源,並且初始化鎖lock為未鎖狀態。
int pthread_spin_lock(pthread_spinlock_t *lock);
鎖住自旋鎖lock。當鎖沒有被某個執行緒持有時,呼叫的執行緒將獲得鎖,否則執行緒將不斷自旋,知道鎖可用。
int pthread_spin_trylock(pthread_spinlock_t *lock);
如果鎖沒有被某個執行緒持有,自旋鎖lock將被鎖住,否則將會失敗。
int pthread_spin_unlock(pthread_spinlock_t *lock);
釋放被鎖住的自旋鎖lock。
(2)基本使用形式
pthread_spin_init(&lock, 0);
…
pthread_spin_lock(&lock);
/*臨界區資源…*/
pthread_spin_unlock(&lock);
pthread_spin_destroy(&lock);
真正需要保護的是資料而不是程式碼,採用特定的鎖保護自己的共享資料。
2、讀-寫自旋鎖
有時,鎖的用途可以明確分為讀取和寫入兩個場景。對一個連結串列可能既要更新又要檢索。當更新(寫入)連寶石,不能有其他程式碼併發地寫或者讀連結串列,寫操作要求完全的護持。另一方面,當對其檢索(讀取)連結串列時,只要求其他程式不對連結串列進行寫操作就行了,可以有多個併發的讀操作。類似於這種情況,就可以通過讀-寫鎖進型保護。
這種鎖的機制照顧寫要多一點,因此,非常適用於讀操作遠多於寫操作的場景,能提高效率。
(1)讀-寫鎖相關函式
使用者態的讀-寫鎖相關函式包含在標頭檔案<pthread.h>中。
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
constpthread_rwlockattr_t *restrict attr);//初始化鎖
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//加讀鎖
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//加寫鎖
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解鎖
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//銷燬鎖
讀-寫自旋鎖的基本使用形式跟自旋鎖差不多。
3、互斥鎖
互斥鎖說白了就是一種互斥的排他鎖-——好比允許睡眠的自旋鎖。
(1)互斥鎖相關的函式
使用者態的互斥鎖相關函式包含在標頭檔案<pthread.h>中。
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
constpthread_mutexattr_t *restrict attr);//初始化鎖
int pthread_mutex_lock(pthread_mutex_t *mutex);//加鎖
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解鎖
int pthread_mutex_destroy(pthread_mutex_t *mutex);//銷燬鎖
(2)基本使用形式
pthread_mutex_init(&mutex);
pthread_mutex_lock(&mutex);//加鎖
/*臨界區…*/
pthread_mutex_unlock(&mutex);//解鎖
自旋鎖與互斥鎖使用對比
需求 |
建議的加鎖方法 |
低開銷加鎖 |
優先使用自旋鎖 |
短期鎖定 |
優先使用自旋鎖 |
長期加鎖 |
優先使用互斥鎖 |
持有鎖需要睡眠 |
使用互斥鎖 |