互斥量mutex
前文提到,系統中如果存在資源共享,執行緒間存在競爭,并且沒有合理的同步機制的話,會出現資料混亂的現象,為了實作同步機制,Linux中提供了多種方式,其中一種方式為互斥鎖mutex(也稱之為互斥量),
互斥量的具體實作方式為:每個執行緒在對共享資源操作前都嘗試先加鎖,成功加鎖后才可以對共享資源進行讀寫操作,操作結束后解鎖,
互斥量不是為了消除競爭,實際上,資源還是共享的,執行緒間也還是競爭的,只不過通過這種“鎖”機制就將共享資源的訪問變成互斥操作,也就是說一個執行緒操作這個資源時,其它執行緒無法操作它,從而消除與時間有關的錯誤,
從互斥量的實作機制我們可以看出,同一時刻,只能有一個執行緒持有該鎖,如果有同時有多個執行緒持有該鎖,那就沒有實際意義了,
但是,這種鎖機制不是強制的,互斥鎖實質上是作業系統提供的一把“建議鎖”(又稱“協同鎖”),建議程式中有多執行緒訪問共享資源的時候使用該機制,
因此,即使有了mutex,其它執行緒如果不按照這種鎖機制來訪問共享資料的話,依然會造成資料混亂,所以為了避免這種情況,所有訪問該共享資源的執行緒必須采用相同的鎖機制,
主要應用函式:
? pthread_mutex_init函式
? pthread_mutex_destroy函式
? pthread_mutex_lock函式
? pthread_mutex_trylock函式
? pthread_mutex_unlock函式
以上5個函式的回傳值都是:成功回傳0,失敗回傳錯誤號,
在Linux環境下,型別pthread_mutex_t其本質是一個結構體,但是為了簡化理解,應用時可忽略其實作細節,簡單當成整數看待,mutex一般以下面方式定義:
pthread_mutex_t mutex;
變數mutex只有兩種取值1、0,
pthread_mutex_init函式
函式原型:
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
函式作用:
初始化一個互斥鎖(互斥量)mutex,初值可視為1;
引數介紹:
mutex:傳出引數,呼叫時應傳 &mutex給該函式;
這里有個關鍵字比較特殊:restrict,它的作用只用于限制指標,告訴編譯器,所有修改該指標指向記憶體中內容的操作,只能通過本指標完成,不能通過除本指標以外的其他變數或指標修改,比如說,再定義個pthread_mutex_t的指標,將其賦值為mutex的值,想要用它來修改mutex所指向的記憶體,這是不允許的,
attr:互斥量屬性,是一個傳入引數,通常傳NULL,表示使用默認屬性(即:執行緒間共享),
對于互斥量mutex的初始化有兩種方式:
1. 靜態初始化:
如果互斥鎖 mutex 是靜態分配的,即:定義為全域變數,或加了static關鍵字修飾,可以直接使用宏進行初始化,e.g. pthead_mutex_t muetx = PTHREAD_MUTEX_INITIALIZER;
2. 動態初始化:
如果互斥鎖mutex定義為區域變數,則應采用動態初始化,e.g. pthread_mutex_init(&mutex, NULL)
pthread_mutex_destroy函式
函式原型:
int pthread_mutex_destroy(pthread_mutex_t *mutex);
函式作用:
銷毀一個互斥鎖
pthread_mutex_lock函式
函式原型:
int pthread_mutex_lock(pthread_mutex_t *mutex);
函式作用:
對共享資源進行加鎖,可理解為將mutex--(或-1);如果加鎖不成功,則該執行緒將阻塞,直到持有該互斥量的其他執行緒解鎖為止,注意:在訪問共享資源前加鎖,訪問結束后立即解鎖,鎖的“粒度”應越小越好,
pthread_mutex_unlock函式
函式原型:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
函式作用:
對共享資源解鎖,可理解為將mutex ++(或+1);在解鎖的同時,會將阻塞在該鎖上的所有執行緒全部喚醒,至于哪個執行緒先被喚醒,取決于優先級、調度,默認情況下:先阻塞的執行緒會先被喚醒,
pthread_mutex_trylock函式
函式原型:
int pthread_mutex_trylock(pthread_mutex_t *mutex);
函式作用:
對共享資源嘗試加鎖,它與pthread_mutex_lock函式的區別是,使用lock函式對共享資源進行加鎖時,如果加鎖不成功,則執行緒就阻塞;而如果使用trylock,則加鎖不成功時不會阻塞當前執行緒,而是立即回傳一個值來描述互斥鎖的狀況,
死鎖:
- 執行緒試圖對同一個互斥量A加鎖兩次,
- 執行緒1擁有A鎖,請求獲得B鎖;執行緒2擁有B鎖,請求獲得A鎖
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex;
void *tfn(void *arg)
{
srand(time(NULL));
while(1) {
pthread_mutex_lock(&mutex);
printf("hello "); // 標準輸出為共享資源
sleep(rand() % 3); // 在此時會失去CPU
printf("world!\n");
pthread_mutex_unlock(&mutex);
sleep(rand() % 3);
}
return NULL;
}
int main()
{
pthread_t tid;
int n = 5;
srand(time(NULL));
pthread_mutex_init(&mutex, NULL);
pthread_create(&tid, NULL, tfn, NULL);
while(n--) {
pthread_mutex_lock(&mutex);
printf("HELLO ");
sleep(rand() % 3);
printf("WORLD!\n");
pthread_mutex_unlock(&mutex);
sleep(rand() % 3);
}
pthread_cancel(tid);
pthread_join(tid, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
更多精彩內容,請關注公眾號良許Linux,公眾內回復1024可免費獲得5T技術資料,包括:Linux,C/C++,Python,樹莓派,嵌入式,Java,人工智能,等等,公眾號內回復進群,邀請您進高手如云技術交流群,
公眾號:良許Linux
有識訓?希望老鐵們來個三連擊,給更多的人看到這篇文章
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/134828.html
標籤:其他
