【Linux 執行緒】執行緒同步《二》
1、讀寫鎖
與互斥量類似,但讀寫鎖允許更高的並行性。其特性為:寫獨佔,讀共享。
讀寫鎖狀態:
一把讀寫鎖具備三種狀態:
(1)讀模式下加鎖狀態 (讀鎖)
(2)寫模式下加鎖狀態 (寫鎖)
(3)不加鎖狀態
讀寫鎖特性:
- 讀寫鎖是"寫模式加鎖"時, 解鎖前,所有對該鎖加鎖的執行緒都會被阻塞。
- 讀寫鎖是"讀模式加鎖"時, 如果執行緒以讀模式對其加鎖會成功;如果執行緒以寫模式加鎖會阻塞。
-
讀寫鎖是"讀模式加鎖"時, 既有試圖以寫模式加鎖的執行緒,也有試圖以讀模式加鎖的執行緒。那麼讀寫鎖會阻塞隨後的讀模式鎖請求。優先滿足寫模式鎖。
讀鎖、寫鎖並行阻塞,寫鎖優先順序高
讀寫鎖也叫共享-獨佔鎖。當讀寫鎖以讀模式鎖住時,它是以共享模式鎖住的;當它以寫模式鎖住時,它是以獨佔模式鎖住的。寫獨佔、讀共享。
讀寫鎖非常適合於對資料結構讀的次數遠大於寫的情況。
主要應用函式:
pthread_rwlock_init函式
pthread_rwlock_destroy函式
pthread_rwlock_rdlock函式
pthread_rwlock_wrlock函式
pthread_rwlock_tryrdlock函式
pthread_rwlock_trywrlock函式
pthread_rwlock_unlock函式
以上7 個函式的返回值都是:成功返回0, 失敗直接返回錯誤號。
pthread_rwlock_t型別 用於定義一個讀寫鎖變數。
pthread_rwlock_t rwlock;
pthread_rwlock_init函式
初始化一把讀寫鎖
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
參2:attr表讀寫鎖屬性,通常使用預設屬性,傳NULL即可。
pthread_rwlock_destroy函式
銷燬一把讀寫鎖
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
pthread_rwlock_rdlock函式
以讀方式請求讀寫鎖。(常簡稱為:請求讀鎖)
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
pthread_rwlock_wrlock函式
以寫方式請求讀寫鎖。(常簡稱為:請求寫鎖)
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
pthread_rwlock_unlock函式
解鎖
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
pthread_rwlock_tryrdlock函式
非阻塞以讀方式請求讀寫鎖(非阻塞請求讀鎖)
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
pthread_rwlock_trywrlock函式
非阻塞以寫方式請求讀寫鎖(非阻塞請求寫鎖)
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
舉例:
1 /************************************************************************* 2 > File Name: pthread_rwlock1.c 3 > Summary: 讀寫鎖示例1 4 > Author: xuelisheng 5 > Created Time: 2018年12月17日 6 ************************************************************************/ 7 8 #include <stdio.h> 9 #include <unistd.h> 10 #include <pthread.h> 11 12 int counter; 13 // 定義全域性的讀寫鎖 14 pthread_rwlock_t rwlock; 15 16 // 3個執行緒不定時呼叫同一全域性資源 17 void *th_write(void *arg) 18 { 19 int t; 20 int i = (int)arg; 21 while(1) 22 { 23 pthread_rwlock_wrlock(&rwlock); // 以寫的方式加鎖,寫獨佔 24 t = counter; 25 usleep(1000); // 寫操作休眠,此時讀操作無法獲得cpu,即無法進行讀操作 26 printf("=====write %d: %lu : counter = %d ++counter = %d\n",i, pthread_self(), t, ++counter); 27 pthread_rwlock_unlock(&rwlock); 28 usleep(10000); 29 } 30 return NULL; 31 } 32 33 void *th_read(void *arg) 34 { 35 int i = (int)arg; 36 37 while(1) 38 { 39 pthread_rwlock_rdlock(&rwlock); // 讀 讀共享 40 printf("------------------------read %d: %lu: %d\n", pthread_self(), counter); 41 pthread_rwlock_unlock(&rwlock); 42 usleep(2000); 43 } 44 return NULL; 45 } 46 47 int main() 48 { 49 int i; 50 pthread_t tid[8]; 51 52 // 初始化讀寫鎖(不管多少個讀寫執行緒,只需一把讀寫鎖) 53 pthread_rwlock_init(&rwlock, NULL); 54 55 // 迴圈建立3個寫執行緒 56 for(i = 0; i<3; i++) 57 pthread_create(&tid[i], NULL, th_write, (void *)i); 58 // 迴圈建立5個讀執行緒 59 for(i = 0; i<5; i++) 60 pthread_create(&tid[i+3], NULL, th_read, (void *)i); 61 62 // 迴圈回收子執行緒 63 for(i = 0; i<8; i++) 64 pthread_join(tid[i], NULL); 65 pthread_rwlock_destroy(&rwlock); 66 67 return 0; 68 }
執行輸出:
擷取部分: ------------------------read 1673803520: 34: 1703023370 ------------------------read 1648625408: 34: 1703023370 ------------------------read 1640232704: 34: 0 =====write 1: 139820055942912 : counter = 34 ++counter = 35 =====write 2: 139820047550208 : counter = 35 ++counter = 36 ------------------------read 1673803520: 36: 0 ------------------------read 1665410816: 36: 0 ------------------------read 1640232704: 36: 0 ------------------------read 1657018112: 36: 1703023370 ------------------------read 1648625408: 36: 0 ------------------------read 1673803520: 36: 0 ------------------------read 1665410816: 36: 0 ------------------------read 1640232704: 36: 0 ------------------------read 1657018112: 36: 0 ------------------------read 1648625408: 36: 0 ------------------------read 1673803520: 36: 0 ------------------------read 1665410816: 36: 0 ------------------------read 1657018112: 36: 3 ------------------------read 1640232704: 36: 2 ------------------------read 1648625408: 36: 1 ------------------------read 1673803520: 36: 0 ------------------------read 1657018112: 36: 1703023370 ------------------------read 1640232704: 36: 1 ------------------------read 1648625408: 36: 2 ------------------------read 1665410816: 36: 1703023370 =====write 0: 139820064335616 : counter = 36 ++counter = 37 ------------------------read 1657018112: 37: 0 ------------------------read 1665410816: 37: 0
觀察可知,滿足讀寫鎖的特性。