pthread的互斥量和自旋鎖

2021-07-15 20:56:03 字數 3244 閱讀 9567

一、自旋鎖與互斥量的區別

在多處理器環境中,自旋鎖最多只能被乙個可執行執行緒持有。如果乙個可執行執行緒試圖獲得乙個被爭用(已經被持有的)自旋鎖,那麼該執行緒就會一直進行忙等待,自旋,也就是空轉,等待鎖重新可用。如果鎖未被爭用,請求鎖的執行執行緒便立刻得到它,繼續執行。乙個被爭用的自旋鎖使得請求它的執行緒在等待鎖重新可用時自旋,特別的浪費cpu時間,所以自旋鎖不應該被長時間的持有。實際上,這就是自旋鎖的設計初衷,在短時間內進行輕量級加鎖。

訊號量和讀寫訊號量適合於保持時間較長的情況,它們會導致呼叫者睡眠,因此只能在程序上下文使用而不能在中斷上下文使用,因為中斷的上下文不允許休眠(trylock可以),因此在中斷上下文只能使用自旋鎖。

自旋鎖保持期間是搶占失效的(核心不允許被搶占) ,而訊號量和讀寫訊號量保持期間是可以被搶占的。

自旋鎖保護的臨界區預設是可以相應中斷的,但是如果在中斷處理程式中請求相同的自旋鎖,那麼會發生死鎖(核心自旋鎖可以關閉中斷)。

二、互斥量

互斥量初始化:動態初始化和編譯期初始化

int pthread_mutex_init(pthread_mutex_t *restrict mutex,

const pthread_mutexattr_t *restrict attr);

pthread_mutex_t mutex = pthread_mutex_initializer;

動態初始化是通過呼叫pthread_mutex_init函式實現的,如果是動態初始化為了防止初始化期間競爭,通常使用下面的方式

static pthread_once_t foo_once = pthread_once_init;

static pthread_mutex_t foo_mutex;

void foo_init()

void foo()

互斥量屬性

int pthread_attr_init(pthread_attr_t* attr);//初始化執行緒屬性物件

int pthread_attr_destroy(pthread_attr_t * attr);//銷毀執行緒屬性物件,被銷毀的執行緒屬性物件只有再次初始化之後才能使用

下面的函式用於獲取和設定執行緒屬性物件的某個屬性

int pthread_mutexattr_init(pthread_mutexattr_t* attr);

int pthread_mutexattr_destroy(pthread_mutexattr_t* attr);

int pthread_mutexattr_getshared(const pthread_mutexattr_t* attr, int* pshared);

int pthread_mutexattr_setshared(pthread_mutexattr_t* attr, int* pshared);

pthread_process_shared:互斥鎖可以被跨程序共享

pthread_process_private:只能被初始化執行緒所屬的程序中的執行緒共享

int pthread_mutexattr_gettype(const pthread_mutexattr_t* attr, int* type);

int pthread_mutexattr_settype(pthread_mutexattr_t* attr, int type);

pthread_mutex_nomal:

公平鎖,對乙個已經加鎖的普通鎖再次加鎖,將引發死鎖;對乙個已經被其他執行緒加鎖的普通鎖解鎖,或者對乙個已經解鎖的普通鎖再次解鎖,將導致不可預期的後果。

pthread_mutex_errorcheck:檢錯鎖,對乙個已經加鎖的檢錯鎖再次加鎖,則加鎖操作返回edeadlock。對乙個已經被其他執行緒加鎖的檢錯鎖解鎖,或者對乙個已經解鎖的檢錯鎖再次解鎖,則解鎖操作返回eperm。

pthread_mutex_recursive:巢狀鎖,錯誤使用返回eperm

pthread_mutex_default:跟nomal差不多。

互斥量操作

對鎖的操作主要包括加鎖 pthread_mutex_lock()、解鎖pthread_mutex_unlock()和測試加鎖 pthread_mutex_trylock()三個。

int pthread_mutex_lock(pthread_mutex_t *mutex)

int pthread_mutex_unlock(pthread_mutex_t *mutex)

int pthread_mutex_trylock(pthread_mutex_t *mutex)

pthread_mutex_trylock()語義與pthread_mutex_lock()類似,不同的是在鎖已經被佔據時返回ebusy而不是掛起等待

注意:

1、執行緒在阻塞等待互斥量的時候可以響應訊號,從訊號處理函式返回之後會依然阻塞等待訊號量,這點與阻塞系統呼叫不同(返回-1,errno=eint)。

2、執行緒在獲取互斥量之後可能被取消(pthread_cancel),因此必須配合使用pthread_cleanup_push / pthread_cleanup_pop系統呼叫釋放以獲取的互斥量。

三、自旋鎖

自旋鎖初始化

int pthread_spin_destroy(pthread_spinlock_t *lock);

int pthread_spin_init(pthread_spinlock_t *lock, int pshared);

如果想要使用自旋鎖同步多程序,那麼設定pshared=pthread_process_shared,然後在程序共享記憶體中分配pthread_spinlock_t 物件即可(pthread_mutex_t亦如此)。

自旋鎖操作

int pthread_spin_lock(pthread_spinlock_t *lock);

int pthread_spin_trylock(pthread_spinlock_t *lock);

int pthread_spin_unlock(pthread_spinlock_t *lock);

自旋鎖,互斥鎖,訊號量

自旋鎖,互斥鎖,訊號量 樂觀鎖和悲觀鎖只是一種理論,是從思想上劃分的。自旋鎖和互斥鎖是應用層確確實實的鎖,用於同步訪問控制 如果一定要劃分,從只有乙個執行緒可以擁有鎖來說,我覺得自旋鎖和互斥鎖應該都屬於悲觀鎖,因為一般的應用不需要支援事物回滾的操作。但是沈詢的直播中說,互斥鎖屬於悲觀鎖 sleep ...

訊號量,互斥鎖,自旋鎖

個人理解 訊號量 程序間的通訊機制 單一個數的訊號 與訊息郵箱,訊息佇列,機理類同,量不同,用訊號量肯定掉cpu 自旋鎖 保護區域不掉cpu,持續查詢,等待 不可用時域長狀態 切記 時域範圍 在程序間的通訊機制函式狀態 鎖 0 互斥鎖與自旋鎖 互斥鎖 執行緒會從sleep 加鎖 running 解鎖...

自旋鎖和互斥鎖

1.理論分析 從理論上說,如果乙個執行緒嘗試加鎖乙個互斥鎖的時候沒有成功,因為互斥鎖已經被鎖住了,這個未獲取鎖的執行緒會休眠以使得其它執行緒可以馬上執行。這個執行緒會一直休眠,直到持有鎖的執行緒釋放了互斥鎖,休眠的執行緒才會被喚醒。如果乙個執行緒嘗試獲得乙個自旋鎖的時候沒有成功,該執行緒會一直嘗試加...