讀寫鎖(rwlock)與互斥鎖(Mutex Lock)相比,有如下特點:
- 更加細緻的區分了讀和寫,給共享資源分別上了“讀”鎖和“寫”鎖。
- “寫”獨佔,“讀”共享,“寫”鎖優先順序更高
- 如果共享資源在絕大多數情況下是“讀”操作,可以提高程式的併發效能。
常用的函式原型總結如下:
pthread_rwlock_t rwlock (= PTHREAD_RWLOCK_INITIALIZER); // 定義讀寫鎖的變數並初始化,一定要全域性變數,如果使用了下述初始化函式,括號內靜態初始化就可以取消
pthread_rwlock_init(&rwlock, NULL); // const pthread_rwlockattr_t *restrict attr,第二個引數預設為NULL
pthread_rwlock_rdlock(&rwlock); // 上讀鎖,並進行讀操作
pthread_rwlock_wrlock(&rwlock); // 上寫鎖,並進行寫操作,同一時間只有一把寫鎖,並與其他鎖互斥
pthread_rwlock_unlock(&rwlock); // 解鎖,讀和寫的解鎖函式都相同
pthread_rwlock_destroy(&rwlock); // 不用了就銷燬讀寫鎖
設計一個程式,程式中有3個執行緒,主執行緒A建立一個文字,每隔5s獲取一次系統時間並寫入到該文字中,另外兩個執行緒B和C分別從文字中讀取當前的時間和日期,子執行緒B輸出系統時間"hh:mm:ss",子執行緒c輸出系統日期"2024年05月31日”,要求使用讀寫鎖實現互斥。 提示:主執行緒A獲取寫操作的鎖,另外的執行緒分別獲取讀操作的鎖,程式如下:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
FILE *timefp; // 以檔案控制代碼為共享區
pthread_rwlock_t rwlock; // 定義讀寫鎖的變數,一定要全域性變數
// 需要用到的時間結構體,提前列出
// struct tm {
// int tm_sec; /* Seconds (0-60) */
// int tm_min; /* Minutes (0-59) */
// int tm_hour; /* Hours (0-23) */
// int tm_mday; /* Day of the month (1-31) */
// int tm_mon; /* Month (0-11) */
// int tm_year; /* Year - 1900 */
// int tm_wday; /* Day of the week (0-6, Sunday = 0) */
// int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */
// int tm_isdst; /* Daylight saving time */
// }
void *funcB(void *arg) // B執行緒
{
time_t tlocB = 0;
while (1)
{
pthread_rwlock_rdlock(&rwlock); // 上鎖,進行讀操作
timefp = fopen("/home/rice/0531/time.txt", "r+");
fread(&tlocB, sizeof(time_t), 1, timefp);
struct tm *tt = localtime(&tlocB);
printf("I am thread B,the time is ===== %02d:%02d:%02d\n", tt->tm_hour, tt->tm_min, tt->tm_sec);
pthread_rwlock_unlock(&rwlock); // 解鎖,釋放許可權
fclose(timefp);
sleep(2); // 每隔兩秒進行一次輸出
}
}
void *funcC(void *arg)
{
time_t tlocC = 0;
while (1)
{
pthread_rwlock_rdlock(&rwlock); // 上鎖,進行讀操作
timefp = fopen("/home/rice/0531/time.txt", "rb+");
fread(&tlocC, sizeof(time_t), 1, timefp);
struct tm *tt = localtime(&tlocC);
printf("I am thread C,the date is ===== %d年:%02d月:%02d日\n", tt->tm_year + 1900, tt->tm_mon + 1, tt->tm_mday);
pthread_rwlock_unlock(&rwlock); // 解鎖,釋放許可權
fclose(timefp);
sleep(2); // 每隔兩秒進行一次輸出
}
}
int main()
{
pthread_rwlock_init(&rwlock, NULL); // 初始化讀寫鎖
pthread_t tidB, tidC;
pthread_create(&tidB, NULL, funcB, NULL); // 建立執行緒
pthread_create(&tidC, NULL, funcC, NULL);
while (1) // 主執行緒每隔5秒獲取一次系統時間
{
pthread_rwlock_wrlock(&rwlock); // 上鎖,進行寫操作
timefp = fopen("/home/rice/0531/time.txt", "wb+"); // 開啟檔案,不存在就建立
time_t tloc = time(NULL);
fwrite(&tloc, sizeof(time_t), 1, timefp); // 將time原始資料存入檔案
fclose(timefp);
pthread_rwlock_unlock(&rwlock); // 解鎖,釋放檔案許可權
sleep(5); // 每隔5秒進行一次寫入操作
}
// 等待B和C執行緒結束
pthread_join(tidB, NULL);
pthread_join(tidC, NULL);
// 銷燬讀寫鎖
pthread_rwlock_destroy(&rwlock);
return 0;
}
輸出結果如下:
I am thread B,the time is ===== 20:10:57
I am thread C,the date is ===== 2024年:06月:01日
I am thread B,the time is ===== 20:10:57
I am thread C,the date is ===== 2024年:06月:01日
I am thread C,the date is ===== 2024年:06月:01日
I am thread B,the time is ===== 20:10:57
I am thread B,the time is ===== 20:11:02
I am thread C,the date is ===== 2024年:06月:01日
I am thread B,the time is ===== 20:11:02
I am thread C,the date is ===== 2024年:06月:01日
...