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

http://www.cnblogs.com/yuuyuu/p/5140251.html

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

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

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

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

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錯誤,就釋放這個線程的所有鎖,不過效率有點低。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384008.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384008.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384008.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

UVa1368

[題目描述] 傳送門 [題目分析] 乍一看好像有點復雜,稍微思考一下只需要找到每個位置中最多的堿基.如果相等的話優先輸出字典序小的. [AC代碼] #include<cstdio> #include<cstring> #include<algorithm> #include<climits> #include<cctype>…

linux線程同步(3)-讀寫鎖

http://www.cnblogs.com/yuuyuu/p/5143881.html 一.概述 讀寫鎖與互斥量的功能類似&#xff0c;對臨界區的共享資源進行保護&#xff01;互斥量一次只讓一個線程進入臨界區&#xff0c;讀寫鎖比它有更高的并行性。讀寫鎖有…

樹的相關筆試面試題

1. 樹的創建 已知一個先序遍歷數的結果用數組表示, 其中空節點用 null_node 表示, 要求創建出這棵樹. 同樣采用遞歸的思想, 先定義一個指針, 指向數組中的第一個元素, 然后給數組的第一個結點創建相應的結點, 然后指針后移, 遞歸創建根節點的左子樹, 遞歸創建根節點的右子樹, …

UVa202

[題目描述] 傳送門 [題目分析] 就是一個模擬,不過稍微有點小復雜,而且輸出格式有點小毒瘤. 不過只是RE了兩發,PE了一發就過了,還是很開心. 需要注意數組要開很大,可能循環節出現在很后. 每個輸出樣例應該輸出一個空行,最后面也應該有,不然會PE [AC代碼] #include<cst…

linux線程同步(5)-屏障

http://www.cnblogs.com/yuuyuu/p/5152560.html 一.概述 barrier(屏障)與互斥量&#xff0c;讀寫鎖&#xff0c;自旋鎖不同&#xff0c;它不是用來保護臨界區的。相反&#xff0c;它跟條件變量一樣&#xff0c;是用來協同多…

淺談軟件測試

一. 什么是軟件測試 軟件測試是一個過程或者一系列過程, 用來測試計算機代碼完成了其應該完成的功能, 不執行不該有的操作.或者說軟件測試是根據軟件開發各階段的功能和說明而精心設計的一批測試用例, 并根據測試用例運行程序, 以發現程序錯誤的過程. 二. 軟件測試的心理學和…

UVa10340

【題目描述】 傳送門 【題目分析】 求字串&#xff0c;最好還是處理母串&#xff0c;每次找到一個子串就加1&#xff0c;這樣處理不用處理細節 【AC代碼】 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include&l…

淺析linux下的條件變量

一.條件變量 條件變量是用來等待線程而不是上鎖的&#xff0c;條件變量通常和互斥鎖一起使用。條件變量之所以要和互斥鎖一起使用&#xff0c;主要是因為互斥鎖的一個明顯的特點就是它只有兩種狀態&#xff1a;鎖定和非鎖定&#xff0c;而條件變量可以通過允許線程阻塞和等待另…

UVa1587

【題目描述】 傳送門 【題目分析】 剛開始想簡單了&#xff0c;認為只要相對的面相等就可以了。然后發現三個不同方向的面的邊應該有相等的關系&#xff0c;即如果兩個面公用一條邊&#xff0c;那么這兩個面的另外兩條邊就是另一個面的兩條邊。而且這三個量里面肯定有一個最…

Linux多線程與同步

https://www.cnblogs.com/freedomabcd/p/7774743.html 典型的UNIX系統都支持一個進程創建多個線程(thread)。在Linux進程基礎中提到&#xff0c;Linux以進程為單位組織操作&#xff0c;Linux中的線程也都基于進程。盡管實現方式有異于其它的UNIX系統&#xff0c;但Linux的多線程…

內存管理(二)

頁面置換算法 當發生缺頁中斷的時候, 系統會在內存中選擇一個頁面將其換出內存, 而當換出內存的時候如果該頁面的內容在內存中發生修改,則必須將該新數據重新寫回到磁盤, 然后再將需要換進的數據覆蓋掉原來的數據, 而當該數據在內存中沒有被修改的時候, 此時就直接用需要換進的…

兩個棧實現一個隊列/兩個隊列實現一個棧

http://blog.csdn.net/sinat_30472685/article/details/70157227 1兩個棧實現一個隊列 1.原理分析&#xff1a; 隊列的主要操作有兩個&#xff1a;入隊操作和出隊操作&#xff0c;出隊時從隊頭出&#xff0c;入隊是從隊尾插入&#xff0c;入隊的操作和入棧的操作類似&#xff0…

UVa1588

【題目描述】 傳送門 【題目分析】 剛開始想了一會沒有想到什么很好的算法&#xff0c;看到了長度最多為100&#xff0c;就知道自己想的沒有什么意義了&#xff0c;直接暴力&#xff0c;把每一種填法都試一下就知道了。適當剪枝一下&#xff08;一個簡單的樂觀函數&#xff…

轉:C++中const、volatile、mutable的用法

const修飾普通變量和指針 const修飾變量&#xff0c;一般有兩種寫法&#xff1a; const TYPE value; TYPE const value; 這兩種寫法在本質上是一樣的。它的含義是&#xff1a;const修飾的類型為TYPE的變量value是不可變的。對于一個非指針的類型TYPE&#xff0c;無論怎么寫&…

數據鏈路

廣播信道的數據鏈路層 局域網的優點 網絡為一個單位所擁有, 地理范圍和站點數有限 局域網具有廣播特性, 可以從一個站點方便地訪問到整個網絡. 各個主機之間可以共享資源, 無論是局域網上的硬件資源還是局域網上的軟件資源 便于系統的擴展換和演化, 各個設備之間的位置可靈…

UVa11809

【題目描述】 傳送門 【題目分析】 終于把這道題做完了&#xff0c;之前一直連題意都看不懂。實在不行上網找了一下大佬的博客&#xff0c;看懂題意后自己寫&#xff0c;發現讀入很難處理&#xff0c;就又學習了一下大佬的讀入方法&#xff0c;用的是C里面的sstream&#xf…

數據鏈路層:基本概念

數據鏈路層的定義 對數據鏈路層有對上的網絡層接口. 對下提供物理層的接口. 定義合適的傳輸差錯率 對傳輸流進行管理, 以免快速的傳輸的數據被淹沒. 比如發送端發送信號太快, 接受方接受速度較慢, 此時數據鏈路層就需要提供一定的功能解決這個問題 物理層上傳輸的基本單元是…

C++的沉迷與愛戀

每年的 09/28 於我都是一個特殊的日子 -- 不只是因為教師節。今年很特殊地沒有普天同慶&#xff0c;那麼我就寫篇文章自己慶祝一下好了。我於今年七月發表了一本著作《多型與虛擬》和一本譯作《深度探索C物件模型》&#xff0c;獲得很大的回響。這些作品都不是針對 C 的完全初學…

Insertion Sort——打表找規律

【題目描述】 Insertion sort is a simple sorting algorithm that builds the final sorted array one item at an iteration.More precisely, insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. At each iteration…

數據鏈路層: 可靠性傳輸 六個協議

可靠性傳輸 1. 差錯控制 發送方將數據幀發送, 但是當發送方發送的是一個 1的時候此時接受方卻接受的是一個 0. (1)校驗 接收方如果幀校驗接受到的幀沒有問題, 則對發送方發送一個肯定性的確認, 當對這個數據幀進行校驗發現這個幀有問題的時候, 此時接受方一種是將這個數據幀…