一、概述
案例:編寫一個案例測試讀寫鎖,要求:新建三個線程寫,5個線程讀,來測試讀寫鎖。
讀寫鎖的基本概念:
讀寫鎖也叫共享-獨占鎖。當讀寫鎖以讀模式鎖住時,它是以共享模式鎖住的;當它以寫模式鎖住時,它是以獨占模式鎖住的。寫獨占,讀共享。
讀寫鎖的使用場合:
對數據結構讀的次數遠大於寫的情況
讀寫鎖的特性:
1.讀寫鎖是“寫模式加鎖”時,解鎖前,所有對該鎖加鎖的線程都會被阻塞
2.讀寫鎖是“讀模式加鎖”時,如果線程以讀模式對其加鎖會成功;如果線程以寫模式加鎖會阻塞。
3.讀寫鎖是“讀模式加鎖”時, 既有試圖以寫模式加鎖的線程,也有試圖以讀模式加鎖的線程。那么讀寫鎖會阻塞隨后的讀模式鎖請求。優先滿足寫模式鎖。讀鎖、寫鎖並行阻塞,寫鎖優先級高
讀寫鎖場景練習:
1. 線程A加寫鎖成功, 線程B請求讀鎖
答:線程B阻塞
2.線程A持有讀鎖, 線程B請求寫鎖
答:線程B阻塞
3.線程A擁有讀鎖, 線程B請求讀鎖
答:線程B加鎖成功
4.線程A持有讀鎖, 然后線程B請求寫鎖, 然后線程C請求讀鎖
答:B阻塞,c阻塞 - 寫的優先級高
5.A解鎖,B線程加寫鎖成功,C繼續阻塞
答:B解鎖,C加讀鎖成功
6.線程A持有寫鎖, 然后線程B請求讀鎖, 然后線程C請求寫鎖
答:BC阻塞
7.A解鎖,C加寫鎖成功,B繼續阻塞
答:C解鎖,B加讀鎖成功
讀寫鎖操作的基本步驟:
1.定義一把鎖:pthread_rwlock_t rwlock;
2.初始化讀寫鎖:pthread_rwlock_init()
3.加讀鎖:pthread_rwlock_rdlock()
4.加寫鎖:pthread_rwlock_wrlock()
5.解鎖:pthread_rwlock_unlock();
6.釋放鎖:pthread_rwlock_destroy();
根據以上6步驟,下面看看具體的代碼示例
二、代碼示例
//讀寫鎖測試程序 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> //定義一個全局變量 int number = 0; //定義一把讀寫鎖 pthread_rwlock_t rwlock; //寫線程回調函數 void * thread_write(void *arg){ int i = *(int *)arg; int cur; while(1){ //加寫鎖 pthread_rwlock_wrlock(&rwlock); cur = number; cur++; number = cur; printf("[%d]-W:[%d]\n",i,cur); //解鎖 pthread_rwlock_unlock(&rwlock); sleep(rand()%3); } } //讀線程回調函數 void *thread_read(void *arg){ int i = *(int *)arg; int cur; while(1){ //加讀鎖 pthread_rwlock_rdlock(&rwlock); cur = number; printf("[%d]-R:[%d]\n",i,cur); //讀寫鎖測試程序 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> //定義一個全局變量 int number = 0; //定義一把讀寫鎖 pthread_rwlock_t rwlock; //寫線程回調函數 void * thread_write(void *arg){ int i = *(int *)arg; int cur; while(1){ //加寫鎖 pthread_rwlock_wrlock(&rwlock); cur = number; cur++; number = cur; printf("[%d]-W:[%d]\n",i,cur); //解鎖 pthread_rwlock_unlock(&rwlock); sleep(rand()%3); } } //讀線程回調函數 void *thread_read(void *arg){ int i = *(int *)arg; int cur; while(1){ //加讀鎖 pthread_rwlock_rdlock(&rwlock); cur = number; printf("[%d]-R:[%d]\n",i,cur); //解鎖 pthread_rwlock_unlock(&rwlock); sleep(rand()%3); } } int main(){ int n = 8; int i =0; int arr[8]; //定義線程 id pthread_t thread[8]; //初始化讀寫鎖 pthread_rwlock_init(&rwlock,NULL); //創建是哪個寫鎖 for(i=0;i<3;i++){ arr[i] = i; //創建寫線程 pthread_create(&thread[i],NULL,thread_write,&arr[i]); } //創建5個讀線程 for(i=3;i<n;i++){ arr[i] = i; //創建讀線程 pthread_create(&thread[i],NULL,thread_read,&arr[i]); } //回收子線程 int j = 0; for(j=0;j<n;j++){ pthread_join(thread[j],NULL); } //釋放鎖 pthread_rwlock_destroy(&rwlock); return 0; }
三、示例圖
如下圖所示:讀出來的數據永遠是寫入的最后一個數據。