日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

互斥量(mutex)

發布時間:2023/11/30 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 互斥量(mutex) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Linux中提供一把互斥鎖mutex(也稱之為互斥量)。每個線程在對資源操作前都嘗試先加鎖,成功加鎖才能操作,操作結束解鎖。資源還是共享的,線程間也還是競爭的,但通過“鎖”就將資源的訪問變成互斥操作,而后與時間有關的錯誤也不會再產生了。但,應注意:同一時刻,只能有一個線程持有該鎖。

當A線程對某個全局變量加鎖訪問,B在訪問前嘗試加鎖,拿不到鎖,B阻塞。C線程不去加鎖,而直接訪問該全局變量,依然能夠訪問,但會出現數據混亂。所以,互斥鎖實質上是操作系統提供的一把“建議鎖”(又稱“協同鎖”,即不加鎖也可以訪問,但是不要這樣做),建議程序中有多線程訪問共享資源的時候使用該機制。但并沒有強制限定。因此,即使有了mutex,如果有線程不按規則來訪問數據,依然會造成數據混亂。Linux操作系統中,用戶層面上編程使用的所有鎖都是建議鎖,不具有強制性,因此訪問共享數據的所有線程(進程)都應該先加鎖才能訪問。

主要應用函數:

pthread_mutex_init函數???????? pthread_mutex_destroy函數

pthread_mutex_lock函數???????? pthread_mutex_trylock函數

pthread_mutex_unlock函數

以上5個函數的返回值都是:成功返回0 失敗返回錯誤號。?????

pthread_mutex_t 類型,其本質是一個結構體。為簡化理解,應用時可忽略其實現細節,簡單當成整數看待。pthread_mutex_t mutex; 變量mutex只有兩種取值1、0。初始化完成后該值為1;加鎖后變為0,解鎖后又變為1。

1pthread_mutex_init函數

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

作用:初始化一個互斥鎖(互斥量) ---> 初值可看作1。參數1:傳出參數,調用時應傳 &mutex;參數2:互斥量屬性。是一個傳入參數,通常傳NULL,選用默認屬性(線程間共享),可參考APUE.12.4同步屬性

restrict關鍵字:只用于限制指針,告訴編譯器,所有修改該指針指向內存中內容的操作,只能通過本指針完成。不能通過除本指針以外的其他變量或指針修改。

靜態初始化:如果互斥鎖 mutex 是靜態分配的(定義在全局,或加static關鍵字修飾),可以直接使用宏進行初始化:pthead_mutex_t muetx = PTHREAD_MUTEX_INITIALIZER;動態初始化:局部變量必須采用動態初始化:pthread_mutex_init(&mutex, NULL)。

2pthread_mutex_destroy函數

int pthread_mutex_destroy(pthread_mutex_t *mutex);

作用:銷毀一個互斥鎖,即釋放資源。

3pthread_mutex_lock函數

int pthread_mutex_lock(pthread_mutex_t *mutex);

作用:加鎖。可理解為將mutex--(或-1)。

4pthread_mutex_unlock函數

int pthread_mutex_unlock(pthread_mutex_t *mutex);

作用:解鎖。可理解為將mutex ++(或+1)。

5pthread_mutex_trylock函數

int pthread_mutex_trylock(pthread_mutex_t *mutex);

作用:嘗試加鎖。lock加鎖失敗會阻塞,等待鎖釋放。?????? trylock加鎖失敗直接返回錯誤號(如:EBUSY),不阻塞。因此,trylock函數要保證能夠加鎖成功需要采用輪詢的方式(每隔一段時間去嘗試加鎖一次),與lock的區別就是不阻塞,類似于wait與waitpid函數。

lockunlock lock嘗試加鎖,如果加鎖不成功,線程阻塞,阻塞到持有該互斥量的其他線程解鎖為止。unlock主動解鎖函數,同時將阻塞在該鎖上的所有線程全部喚醒,至于哪個線程先被喚醒,取決于優先級、調度。默認:先阻塞、先喚醒。例如:T1 T2 T3 T4 使用一把mutex鎖。T1加鎖成功,其他線程均阻塞,直至T1解鎖。T1解鎖后,T2 T3 T4均被喚醒,并自動再次嘗試加鎖。

可假想mutex鎖 init成功初值為1。 lock 功能是將mutex--。unlock將mutex++。

看如下程序:該程序是非常典型的,由于共享、競爭而沒有加任何同步機制,導致產生于時間有關的錯誤,造成數據混亂:

//線程之間共享資源stdout(標準輸出)

#include <stdio.h> #include <string.h> #include <pthread.h> #include <stdlib.h> #include <unistd.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(void) {int flg = 5;pthread_t tid;srand(time(NULL));pthread_mutex_init(&mutex, NULL); // mutex=1pthread_create(&tid, NULL, tfn, NULL);while (flg--) {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; }

//采用mutex鎖機制的輸出情況

[root@localhost 02_pthread_sync_test]# ./mutex

HELLO WORLD

hello world

HELLO WORLD

HELLO WORLD

hello world

HELLO WORLD

HELLO WORLD

hello world

hello world

//不采用mutex鎖機制的輸出情況(刪除上述程序中的鎖)

[root@localhost 02_pthread_sync_test]# ./mutex

HELLO hello world

WORLD

HELLO hello WORLD

HELLO world

hello world

WORLD

hello HELLO WORLD

HELLO world

WORLD

分析:

  • 注意srand( time(NULL) ); ?rand( )函數的用法:產生非假隨機數;
  • 兩個線程while中,兩次printf前后,分別加lock和unlock。如果將unlock挪至第二個sleep函數后面,發現交替現象很難出現。這是因為線程在操作完共享資源后本應該立即解鎖,但修改后,線程抱著鎖睡眠。睡醒解鎖后又立即加鎖,這兩個庫函數本身不會阻塞。所以在這兩行代碼之間失去cpu的概率很小。因此,另外一個線程很難得到加鎖的機會。因此:在訪問共享資源前加鎖,訪問結束后立即解鎖。鎖的“粒度”應越小越好。
  • 總結

    以上是生活随笔為你收集整理的互斥量(mutex)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。