1. 程式人生 > >【Linux 執行緒】執行緒同步《二》

【Linux 執行緒】執行緒同步《二》

1、讀寫鎖

與互斥量類似,但讀寫鎖允許更高的並行性。其特性為:寫獨佔,讀共享

讀寫鎖狀態:

一把讀寫鎖具備三種狀態:

    (1)讀模式下加鎖狀態 (讀鎖)

    (2)寫模式下加鎖狀態 (寫鎖)

    (3)不加鎖狀態

讀寫鎖特性:    

  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

觀察可知,滿足讀寫鎖的特性。