c 執行緒中的幾種鎖

2021-08-25 11:22:26 字數 3384 閱讀 2339

這個是在中興面試中被面試問到的乙個題「你知道執行緒中的自旋鎖麼?」,我當時一臉懵逼,不知道。回來後整理下,在這裡對執行緒中的鎖進行乙個學習。

執行緒之間的鎖有:互斥鎖、條件鎖、自旋鎖、讀寫鎖、遞迴鎖。一般而言,鎖的功能越強大,效能就會越低。

1、互斥鎖

互斥鎖用於控制多個執行緒對他們之間共享資源互斥訪問的乙個訊號量。也就是說是為了避免多個執行緒在某一時刻同時操作乙個共享資源。例如執行緒池中的有多個空閒執行緒和乙個任務佇列。任何是乙個執行緒都要使用互斥鎖互斥訪問任務佇列,以避免多個執行緒同時訪問任務佇列以發生錯亂。

在某一時刻,只有乙個執行緒可以獲取互斥鎖,在釋放互斥鎖之前其他執行緒都不能獲取該互斥鎖。如果其他執行緒想要獲取這個互斥鎖,那麼這個執行緒只能以阻塞方式進行等待。

標頭檔案:

型別:pthread_mutex_t,

函式:pthread_mutex_init(pthread_mutex_t * mutex, const phtread_mutexattr_t * mutexattr);//動態方式建立鎖,相當於new動態建立乙個物件

pthread_mutex_destory(pthread_mutex_t *mutex)//釋放互斥鎖,相當於delete

pthread_mutex_t mutex = pthread_mutex_initializer;//以靜態方式建立鎖

pthread_mutex_lock(pthread_mutex_t *mutex)//以阻塞方式執行的。如果之前mutex被加鎖了,那麼程式會阻塞在這裡。

pthread_mutex_unlock(pthread_mutex_t *mutex)

int pthread_mutex_trylock(pthread_mutex_t * mutex);//會嘗試對mutex加鎖。如果mutex之前已經被鎖定,返回非0,;如果mutex沒有被鎖定,則函式返回並鎖定mutex

//該函式是以非阻塞方式執行了。也就是說如果mutex之前已經被鎖定,函式會返回非0,程式繼續往下執行。

2、條件鎖

標頭檔案:

型別:pthread_cond_t

函式:pthread_cond_init(pthread_cond_t * condtion, const phtread_condattr_t * condattr);//對條件變數進行動態初始化,相當於new建立物件

pthread_cond_destory(pthread_cond_t * condition);//釋放動態申請的條件變數,相當於delete釋放物件

pthread_cond_t condition = pthread_cond_initializer;//靜態初始化條件變數

pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex);//該函式以阻塞方式執行。如果某個執行緒中的程式執行了該函式,那麼這個執行緒就會以阻塞方式等待,直到收到pthread_cond_signal或者pthread_cond_broadcast函式發來的訊號而被喚醒。

注意:pthread_cond_wait函式的語義相當於:首先解鎖互斥鎖,然後以阻塞方式等待條件變數的訊號,收到訊號後又會對互斥鎖加鎖。

為了防止「虛假喚醒」,該函式一般放在while迴圈體中。例如

pthread_mutex_lock(mutex);//加互斥鎖

while(條件不成立)//當前執行緒中條件變數不成立

...//對程序之間的共享資源進行操作

pthread_mutex_unlock(mutex);//釋放互斥鎖

pthread_cond_signal(pthread_cond_t * cond);//在另外乙個執行緒中改變執行緒,條件滿足傳送訊號。喚醒乙個等待的執行緒(可能有多個執行緒處於阻塞狀態),喚醒哪個執行緒由具體的執行緒排程策略決定

pthread_cond_broadcast(pthread_cond_t * cond);//以廣播形式喚醒所有因為該條件變數而阻塞的所有執行緒,喚醒哪個執行緒由具體的執行緒排程策略決定

pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex, struct timespec * time);//以阻塞方式等待,如果時間time到了條件還沒有滿足還是會結束

3、自旋鎖

前面的兩種鎖是比較常見的鎖,也比較容易理解。下面通過比較互斥鎖和自旋鎖原理的不同,這對於真正理解自旋鎖有很大幫助。

假設我們有乙個兩個處理器core1和core2計算機,現在在這台計算機上執行的程式中有兩個執行緒:t1和t2分別在處理器core1和core2上執行,兩個執行緒之間共享著乙個資源。

首先我們說明互斥鎖的工作原理,互斥鎖是是一種sleep-waiting的鎖。假設執行緒t1獲取互斥鎖並且正在core1上執行時,此時執行緒t2也想要獲取互斥鎖(pthread_mutex_lock),但是由於t1正在使用互斥鎖使得t2被阻塞。當t2處於阻塞狀態時,t2被放入到等待佇列中去,處理器core2會去處理其他任務而不必一直等待(忙等)。也就是說處理器不會因為執行緒阻塞而空閒著,它去處理其他事務去了。

而自旋鎖就不同了,自旋鎖是一種busy-waiting的鎖。也就是說,如果t1正在使用自旋鎖,而t2也去申請這個自旋鎖,此時t2肯定得不到這個自旋鎖。與互斥鎖相反的是,此時執行t2的處理器core2會一直不斷地迴圈檢查鎖是否可用(自旋鎖請求),直到獲取到這個自旋鎖為止。

從「自旋鎖」的名字也可以看出來,如果乙個執行緒想要獲取乙個被使用的自旋鎖,那麼它會一致占用cpu請求這個自旋鎖使得cpu不能去做其他的事情,直到獲取這個鎖為止,這就是「自旋」的含義。

當發生阻塞時,互斥鎖可以讓cpu去處理其他的任務;而自旋鎖讓cpu一直不斷迴圈請求獲取這個鎖。通過兩個含義的對比可以我們知道「自旋鎖」是比較耗費cpu的

標頭檔案:

自旋鎖的型別:spinlock_t

spin_lock(x);   //只有在獲得鎖的情況下才返回,否則一直「自旋」

spin_trylock(x);  //如立即獲得鎖則返回真,否則立即返回假

釋放鎖:spin_unlock(x);

spin_is_locked(x)//  該巨集用於判斷自旋鎖x是否已經被某執行單元保持(即被鎖),如果是,   返回真,否則返回假。

注意:自旋鎖適合於短時間的的輕量級的加鎖機制。

4、讀寫鎖

說到讀寫鎖我們可以借助於「讀者-寫者」問題進行理解。首先我們簡單說下「讀者-寫者」問題。

計算機中某些資料被多個程序共享,對資料庫的操作有兩種:一種是讀操作,就是從資料庫中讀取資料不會修改資料庫中內容;另一種就是寫操作,寫操作會修改資料庫中存放的資料。因此可以得到我們允許在資料庫上同時執行多個「讀」操作,但是某一時刻只能在資料庫上有乙個「寫」操作來更新資料。這就是乙個簡單的讀者-寫者模型。

c 執行緒中的幾種鎖

這個是在中興面試中被面試問到的乙個題 你知道執行緒中的自旋鎖麼?我當時一臉懵逼,不知道。回來後整理下,在這裡對執行緒中的鎖進行乙個學習。執行緒之間的鎖有 互斥鎖 條件鎖 自旋鎖 讀寫鎖 遞迴鎖。一般而言,鎖的功能越強大,效能就會越低。1 互斥鎖 互斥鎖用於控制多個執行緒對他們之間共享資源互斥訪問的乙...

c 執行緒中的幾種鎖

執行緒之間的鎖有 互斥鎖 條件鎖 自旋鎖 讀寫鎖 遞迴鎖。一般而言,鎖的功能越強大,效能就會越低。1 互斥鎖 互斥鎖用於控制多個執行緒對他們之間共享資源互斥訪問的乙個訊號量。也就是說是為了避免多個執行緒在某一時刻同時操作乙個共享資源。例如執行緒池中的有多個空閒執行緒和乙個任務佇列。任何是乙個執行緒都...

c 執行緒中的幾種鎖

互斥鎖用於控制多個執行緒對他們之間共享資源互斥訪問的乙個訊號量。也就是說是為了避免多個執行緒在某一時刻同時操作乙個共享資源。例如執行緒池中的有多個空閒執行緒和乙個任務佇列。任何是乙個執行緒都要使用互斥鎖互斥訪問任務佇列,以避免多個執行緒同時訪問任務佇列以發生錯亂。在某一時刻,只有乙個執行緒可以獲取互...