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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux线程同步(1)-互斥量

發布時間:2025/3/21 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux线程同步(1)-互斥量 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.概述 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

互斥量是線程同步的一種機制,用來保護多線程的共享資源。同一時刻,只允許一個線程對臨界區進行訪問。

互斥量的工作流程:創建一個互斥量,把這個互斥量的加鎖調用放在臨界區的開始位置,解鎖調用放到臨界區的結束位置。當內核優先把某個線程調度到臨界區的開始位置時,線程執行這個加鎖調用,并進入臨界區對資源進行操作。此時其他線程再被內核調度到這里的時候,由于該互斥量已被加鎖狀態,得不到鎖會一直阻塞在這里,導致其他線程不能進入臨界區,直到剛剛那個進入臨界區的線程離開臨界區并執行解鎖調用。

二.函數接口 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

1.初始化互斥量

互斥量是一個pthread_mutex_t類型的變量。

1.1:用宏常量初始化:

1 pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

1.2:用函數初始化:

1 #include <pthread.h> 2 3 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

mutex:互斥量結構指針

attr:互斥量的屬性結構指針

2.設置互斥量屬性

1 #include <pthread.h> 2 3 int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);

attr:互斥量的屬性結構指針

type:PTHREAD_MUTEX_NORMAL(默認屬性),PTHREAD_MUTEX_ERRORCHECK(會進行錯誤檢查,速度比較慢),PTHREAD_MUTEX_RECURSIVE(遞歸鎖)。對于遞歸鎖,同一個線程對一個遞歸鎖加鎖多次,會有一個鎖計數器,解鎖的時候也需要解鎖這個次數才能釋放該互斥量。

3.加鎖與解鎖

1 #include <pthread.h> 2 3 int pthread_mutex_lock(pthread_mutex_t *mutex); 4 int pthread_mutex_trylock(pthread_mutex_t *mutex); 5 int pthread_mutex_unlock(pthread_mutex_t *mutex);

參數都是互斥量指針。pthread_mutex_lock()得不到鎖會阻塞,int pthread_mutex_trylock()得不到鎖會立即返回,并返回EBUSY錯誤。

還有一個pthread_mutex_timedlock()會根據時間來等待加鎖,如果這段時間得不到鎖會返回ETIMEDOUT錯誤!

1 #include <pthread.h> 2 #include <time.h> 3 4 int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timespec *restrict abs_timeout);

4.銷毀互斥量

1 #include <pthread.h> 2 3 int pthread_mutex_destroy(pthread_mutex_t *mutex);

mutex:創建的互斥量指針

三.簡單例子 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

寫個簡單的例子,主線程消費,子線程生產,并模擬使用過程中可能遇到的缺點

1 /** 2 * @file pthread_mutex.c 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <unistd.h> 9 #include <pthread.h> 10 11 /* 定義互斥量 */ 12 pthread_mutex_t mtx; 13 /* 互斥量屬性 */ 14 pthread_mutexattr_t mtx_attr; 15 /* 全局資源 */ 16 int money; 17 18 void err_exit(const char *err_msg) 19 { 20 printf("error:%s\n", err_msg); 21 exit(1); 22 } 23 24 /* 線程函數 */ 25 void *thread_fun(void *arg) 26 { 27 while (1) 28 { 29 /* 加鎖 */ 30 pthread_mutex_lock(&mtx); 31 32 printf("子線程進入臨界區查看money\n"); 33 if (money == 0) 34 { 35 money += 200; 36 printf("子線程:money = %d\n", money); 37 } 38 39 /* 解鎖 */ 40 pthread_mutex_unlock(&mtx); 41 42 sleep(1); 43 } 44 45 return NULL; 46 } 47 48 int main(void) 49 { 50 pthread_t tid; 51 52 /* 初始化互斥量屬性 */ 53 if (pthread_mutexattr_init(&mtx_attr) == -1) 54 err_exit("pthread_mutexattr_init()"); 55 56 /* 設置互斥量屬性 */ 57 if (pthread_mutexattr_settype(&mtx_attr, PTHREAD_MUTEX_NORMAL) == -1) 58 err_exit("pthread_mutexattr_settype()"); 59 60 /* 初始化互斥量 */ 61 if (pthread_mutex_init(&mtx, &mtx_attr) == -1) 62 err_exit("pthread_mutex_init()"); 63 64 /* 創建一個線程 */ 65 if (pthread_create(&tid, NULL, thread_fun, NULL)== -1) 66 err_exit("pthread_create()"); 67 68 money = 1000; 69 while (1) 70 { 71 /* 加鎖 */ 72 pthread_mutex_lock(&mtx); 73 74 if (money > 0) 75 { 76 money -= 100; 77 printf("主線程:money = %d\n", money); 78 } 79 80 /* 解鎖 */ 81 pthread_mutex_unlock(&mtx); 82 83 sleep(1); 84 } 85 86 return 0; 87 }

主線程和子線程都對money的操作進行了互斥量保護。68行,初始化money是1000,主線程每次消耗100,子線程只有到money是0是才會生產。sleep(1)防止獨占cpu,也方便打印信息。編譯運行:

可以看到這里有個非常浪費資源的問題:主線程消耗money的時候,子線程它不知道什么時候才消耗完,每次內核調度到它時,它都進入臨界區加鎖互斥量,然后查看money,再解鎖。這無意義的操作,簡直是極大的浪費!有什么辦法可以解決這個問題呢?它有一個好伙伴,叫條件變量

四.死鎖 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

假設:當線程1獲取鎖1,再獲取鎖2后才能進入臨界區1,線程2獲取鎖2,再獲取鎖1才能進入臨界區2。某個時刻,線程1獲取了鎖1,再去獲取鎖2的時候發現鎖2已經被線程2鎖住了,而線程2獲取鎖2后,發現鎖1被線程1鎖住了。這樣2個線程誰也不讓誰,都進不了自己的臨界區,就產生了死鎖現象!一般遇到這種情況常見的解決辦法是:規定統一的加鎖順序。線程1和線程2都按照先鎖1,再鎖2。還一種就是使用pthread_mutex_trylock(),如果該函數返回EBUSY錯誤,就釋放這個線程的所有鎖,不過效率有點低。

總結

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

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