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

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

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

讀寫鎖與互斥量的功能類似,對臨界區的共享資源進行保護!互斥量一次只讓一個線程進入臨界區,讀寫鎖比它有更高的并行性。讀寫鎖有以下特點:

1.如果一個線程用讀鎖鎖定了臨界區,那么其他線程也可以用讀鎖來進入臨界區,這樣就可以多個線程并行操作。但這個時候,如果再進行寫鎖加鎖就會發生阻塞,寫鎖請求阻塞后,后面如果繼續有讀鎖來請求,這些后來的讀鎖都會被阻塞!這樣避免了讀鎖長期占用資源,防止寫鎖饑餓

2.如果一個線程用寫鎖鎖住了臨界區,那么其他線程不管是讀鎖還是寫鎖都會發生阻塞!

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

1.創建讀寫鎖

1.1:宏常量初始化

1 pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

1.2:函數初始化

1 #include <pthread.h>
2 
3 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);

rwlock:讀寫鎖的pthread_rwlock_t結構指針

attr:讀寫鎖的屬性結構指針。不需要別的屬性默認為NULL。

2.讀寫鎖加鎖與解鎖

1 #include <pthread.h>
2 
3 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
4 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
5 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

rwlock:創建的讀寫鎖指針

3.其他類型的加鎖

復制代碼
1 #include <pthread.h>
2 #include <time.h>
3 
4 
5 int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
6 int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
7 
8 int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
9 int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
復制代碼

try類函數加鎖:如果獲取不到鎖,會立即返回錯誤EBUSY

timed類函數加鎖:如果規定的時間內獲取不到鎖,會返回ETIMEDOUT錯誤!

4.銷毀讀寫鎖

1 #include <pthread.h>
2 
3 int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

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

創建4個線程,2個線程讀鎖,2個線程寫鎖,觀察4個線程進入臨界區的順序

復制代碼
 1 /**
 2  * @file pthread_rwlock.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_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
13 /* 全局資源 */
14 int global_num = 10;
15 
16 void err_exit(const char *err_msg)
17 {
18     printf("error:%s\n", err_msg);
19     exit(1);
20 }
21 
22 /* 讀鎖線程函數 */
23 void *thread_read_lock(void *arg)
24 {
25     char *pthr_name = (char *)arg;
26 
27     while (1)
28     {
29         /* 讀加鎖 */
30         pthread_rwlock_rdlock(&rwlock);
31 
32         printf("線程%s進入臨界區,global_num = %d\n", pthr_name, global_num);
33         sleep(1);
34         printf("線程%s離開臨界區...\n", pthr_name);
35 
36         /* 讀解鎖 */
37         pthread_rwlock_unlock(&rwlock);
38 
39         sleep(1);
40     }
41 
42     return NULL;
43 }
44 
45 /* 寫鎖線程函數 */
46 void *thread_write_lock(void *arg)
47 {
48     char *pthr_name = (char *)arg;
49 
50     while (1)
51     {
52         /* 寫加鎖 */
53         pthread_rwlock_wrlock(&rwlock);
54 
55         /* 寫操作 */
56         global_num++;
57         printf("線程%s進入臨界區,global_num = %d\n", pthr_name, global_num);
58         sleep(1);
59         printf("線程%s離開臨界區...\n", pthr_name);
60 
61         /* 寫解鎖 */
62         pthread_rwlock_unlock(&rwlock);
63 
64         sleep(2);
65     }
66 
67     return NULL;
68 }
69 
70 int main(void)
71 {
72     pthread_t tid_read_1, tid_read_2, tid_write_1, tid_write_2;
73 
74     /* 創建4個線程,2個讀,2個寫 */
75     if (pthread_create(&tid_read_1, NULL, thread_read_lock, "read_1") != 0)
76         err_exit("create tid_read_1");
77 
78     if (pthread_create(&tid_read_2, NULL, thread_read_lock, "read_2") != 0)
79         err_exit("create tid_read_2");
80 
81     if (pthread_create(&tid_write_1, NULL, thread_write_lock, "write_1") != 0)
82         err_exit("create tid_write_1");
83 
84     if (pthread_create(&tid_write_2, NULL, thread_write_lock, "write_2") != 0)
85         err_exit("create tid_write_2");
86 
87     /* 隨便等待一個線程,防止main結束 */
88     if (pthread_join(tid_read_1, NULL) != 0)
89         err_exit("pthread_join()");
90 
91     return 0;
92 }
復制代碼

2個線程函數的臨界區里面都sleep(1),測試給足夠的時間看其他線程能不能進來。64行,寫鎖函數里面,sleep(2),因為寫鎖請求會阻塞后面的讀鎖,2個寫鎖一起請求會讓讀鎖饑餓,所以比39行的sleep(1)多一秒!

編譯運行:

可以看到,讀鎖可以一起進入臨界區,而寫鎖在臨界區里面等1秒都不會有其他線程能進來!!!


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

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

相關文章

樹的相關筆試面試題

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)校驗 接收方如果幀校驗接受到的幀沒有問題, 則對發送方發送一個肯定性的確認, 當對這個數據幀進行校驗發現這個幀有問題的時候, 此時接受方一種是將這個數據幀…

c語言實現配置文件的讀寫

配置文件的格式如下&#xff1a; key1 value1 key2 value2 . . . 名值對以一個鏈接&#xff0c;一條記錄以換行符分割 頭文件&#xff1a; #include<stdio.h> #include<stdlib.h> #include <string.h> 函數原型&#xff1a; void trim(char *strIn, char *…

Educational Codeforces Round 73 (Rated for Div. 2)

A 很簡單的一個模擬&#xff0c;只要前面的數字有兩個以上就能合成后面的&#xff0c;我們進行一遍合成看能不能出現2048就可以了。 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include&…