Linux執行緒同步(一)之使用互斥量(互斥鎖)

2021-08-09 04:53:44 字數 3689 閱讀 4028

當多個控制線程共享相同的記憶體時,需要確保每個執行緒看到一致的資料檢視。如果每個執行緒使用的變數都是其他執行緒不會讀取或修改的,那麼就不存在一致性問題。同樣地,如果變數是唯讀的,多個執行緒同時讀取該量也不會有一致性問題。但是,當某個執行緒可以修改變數,而其他執行緒也可以讀取或者修改這個變數的時候,就需要對這些執行緒進行同步,以確保它們在訪問變數的儲存內容時不會訪問到無效的資料。

可以通過使用pthread的互斥介面保護資料,確保同一時間只有乙個執行緒訪問資料。

1、互斥量從本質上說是一把鎖,在訪問共享資源前對互斥量進行加鎖,在訪問完成之後釋放互斥量上的鎖。對互斥量進行加鎖以後,任何其他試圖再次對互斥量加鎖的執行緒將會被阻塞直到當前執行緒釋放該互斥鎖。如果釋放互斥鎖時有多個執行緒阻塞,所有在該互斥鎖上的阻塞執行緒都會變成可執行狀態,第乙個變為執行狀態的執行緒可以對互斥量加鎖,其他執行緒將會看到互斥鎖依然被鎖住,只能回去再次等待它重新變為可用。在這種方式下,每次只能有乙個執行緒可以向前執行。

2、互斥鎖是用來實現執行緒訪問臨界資源的同步控制。如果乙個執行緒在臨界區開始時,給互斥鎖加鎖,那麼其他的執行緒就必須等待執行緒解鎖,才能接著執行,並訪問資源。

1、互斥量的初始化和銷毀

互斥變數用pthread_mutex_t資料型別來表示,在使用互斥變數以前,必須首先對它進行初始化,可以把它置為常量pthread_mutex_initializer(只對靜態分配的互斥量),也可以通過呼叫pthread_mutex_init函式進行初始化。如果動態地分配互斥量(例如通過呼叫malloc函式),那麼在釋放記憶體前需要呼叫pthread_mutex_destroy函式。

鎖的初始化和銷毀函式的原型如下:

#include 

int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * attr);

int pthread_mutex_destroy(pthread_mutex_t *mutex);

返回值:若成功則返回0,否則返回錯誤編號。

要用預設的屬性初始化互斥量,只需把attr設定為null。

非預設的互斥量屬性有:程序共享屬性和型別屬性

2、互斥量的加鎖和解鎖

對互斥量進行加鎖,需要呼叫pthread_mutex_lock函式,如果互斥量已經上鎖,呼叫執行緒將阻塞直到互斥量被解鎖,需要呼叫pthread_mutex_unlock函式。

#include 

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutext_unlock(pthread_mutex_t *mutex);

返回值:若成功則返回0,否則返回錯誤編號。

如果執行緒不希望被阻塞,它可以使用pthread_mutex_trylock函式嘗試對互斥量進行加鎖。如果呼叫pthread_mutex_trylock時互斥量處於未鎖住狀態,那麼pthread_mutex_trylock將鎖住互斥量,不會出現阻塞並返回0,否則pthread_mutex_trylock就會失敗,不會鎖住互斥量,而返回ebusy。

3、**舉例

(1)主線程負責接收使用者輸入,函式執行緒統計使用者輸入的字元個數。

#include 

#include

#include

#include

#include

#include

char buf[128] = ;//定義全域性臨界資源

pthread_mutex_t p;//定義全域性互斥量

//函式執行緒

void * fun_pthread1(void *arg)

int count = 0;

while(1)

count++;

}printf("count:%d\n",count);//列印主線程每次輸入的字元個數

pthread_mutex_unlock(&p);//給互斥量解鎖

sleep(1);

}}int main()

sleep(1);

pthread_mutex_lock(&p);

}pthread_join(id,null);//等待函式執行緒結束再執行,第二個引數接收函式執行緒結束時傳遞的資訊,null表示無資訊。

pthread_mutex_destroy(&p);//當函式執行緒結束時,銷毀互斥量

// pthread_exit(null);//主線程退出時,函式執行緒不一定結束,如果使用exit函式(預設)退出,那麼程序就會結束,所有包含在程序中的執行緒也會結束,可能導致函式執行緒未執行完突然結束

return

0;}

結果展示:

(2)實現主線程迴圈接收使用者輸入,以「end」作為結束標誌,函式執行緒統計使用者每次輸入的單詞個數,最後再統計總輸入的單詞個數。

#include 

#include

#include

#include

#include

#include

char buf[128] = ;//臨界資源

pthread_mutex_t p;//互斥量

int sum = 0;

//函式執行緒

void * fun_pthread1(void *arg)

int flag = 1;

int count = 0;

int len = strlen(buf);

int i;

for(i=0;i// 判斷是不是空格,是的話flag=1

// 不是的話,判斷前面是不是空格即flag是否等於1

// 是空格的話,說明是新單詞的開始

if(buf[i] == '\n')

if(buf[i] == ' ')

else

if(flag == 1)}}

printf("count:%d\n",count);//列印本次輸入的單詞個數

sum += count;

pthread_mutex_unlock(&p);

sleep(1);

}}int main()

sleep(1);

pthread_mutex_lock(&p);

}pthread_join(id,null);

pthread_mutex_destroy(&p);

printf("sum = %d\n",sum);//列印總輸入的單詞個數

return

0;}

結果演示:

linux執行緒》同步互斥機制之 互斥鎖

本文基於訊號量 如果訊號量的值最多為1,那實際上相當於乙個共享資源在任意時刻最多只能有乙個執行緒在訪問,這樣的邏輯稱為 互斥 這時,有一種更加方便和語義更加準確的工具來滿足這種邏輯 互斥鎖。幾個執行緒同時去搶乙個鎖,誰搶到了鎖就進門把房間鎖上,訪問資料,出來後之前解鎖。照這樣的邏輯,互斥鎖的操作無非...

Linux多執行緒 使用互斥量同步執行緒

原部落格 linux多執行緒 使用訊號量同步執行緒 只有子執行緒結束了對輸入的處理和統計後,主線程才能繼續執行的問題。一 什麼是互斥量 互斥量是另一種用於多執行緒中的同步訪問方法,它允許程式鎖住某個物件,使得每次只能有乙個執行緒訪問它。為了控制對關鍵 的訪問,必須在進入這段 之前鎖住乙個互斥量,然後...

Linux多執行緒 使用互斥量同步執行緒

linux多執行緒 使用訊號量同步執行緒 只有子執行緒結束了對輸入的處理和統計後,主線程才能繼續執行的問題。一 什麼是互斥量 互斥量是另一種用於多執行緒中的同步訪問方法,它允許程式鎖住某個物件,使得每次只能有乙個執行緒訪問它。為了控制對關鍵 的訪問,必須在進入這段 之前鎖住乙個互斥量,然後在完成操作...