-
概述
在某些場景下,讀資料操作比寫資料操作要頻繁,那麼可以使用讀寫鎖替代互斥鎖來提高應用程式的性能。
讀寫鎖的通路規則如下:
- 多個線程共享讀操作權限
- 沒有讀或者寫操作時,才可以執行寫操作
- 主要操作
#include <pthread.h>
int pthread_rwclock_rdclock(pthread_rwlock_t *rwptr);//加讀出鎖,如果讀寫鎖被一個寫入者持有則堵塞
int pthread_rwclock_wrclock(pthread_rwlock_t *rwptr);//加寫入鎖,如果讀寫鎖被讀或者寫線程占有,則堵塞等待
int pthread_rwclock_unclock(pthread_rwlock_t *rwptr);//釋放鎖
// 非阻塞模式,如果不能馬上得到就傳回一個EBUSY錯誤
int pthread_rwclock_tryrdclock(pthread_rwlock_t *rwptr);
int pthread_rwclock_trywrclock(pthread_rwlock_t *rwptr);
讀寫鎖的初始化和銷毀
int pthread_rwclock_init(pthread_rwlock_t *rwptr, const pthread_rwlockattr_t *attr);
int pthread_rwclock_destory(pthread_rwlock_t *rwptr);
設定讀寫鎖屬性,屬性值為PTHREAD_PROCESS_PRIVATE或 PTHREAD_PROCESS_SHARED。前者表是讀寫鎖隻在本程序可用,後者表示可以多程序共享。
int pthread_rwclock_getpshared(const pthread_rwlockattr_t *attr, int *valptr);
int pthread_rwclock_setpshared(const pthread_rwlockattr_t *attr, int valptr);
- 舉例
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
long g_data = 0;
pthread_rwlock_t lock; //讀寫鎖
void* wr_cb(void* arg) {
while (1) {
//加寫入鎖
pthread_rwlock_wrlock(&lock);
g_data++;
usleep(10);
printf("write clock, thread id: %lu, data: %d\n", pthread_self(),
g_data);
//釋放鎖
pthread_rwlock_unlock(&lock);
usleep(1000);
}
return NULL;
}
void* rd_cb(void* arg) {
while (1) {
//加讀出鎖
pthread_rwlock_rdlock(&lock);
printf("read clock, thread id: %lu, data: %d\n", pthread_self(),
g_data);
//釋放鎖
pthread_rwlock_unlock(&lock);
usleep(1000);
}
return NULL;
}
int main(int argc, char* argv[]) {
pthread_t thd[4]; // 4個線程
pthread_create(&thd[0], NULL, wr_cb, NULL);
pthread_create(&thd[1], NULL, wr_cb, NULL);
pthread_create(&thd[2], NULL, rd_cb, NULL);
pthread_create(&thd[3], NULL, rd_cb, NULL);
int i;
for (i = 0; i < 4; i++) {
pthread_join(thd[i], NULL);
}
//銷毀
pthread_rwlock_destroy(&lock);
return 0;
}
-
總結
讀寫鎖的特性
- 加讀出鎖: 來了N個線程做讀出操作,那麼都加鎖成功, 這叫讀鎖共享。如果先來了M個線程做讀出操作,後來了K個線程做寫入操作,又來了L個線程做讀操作。那麼從K個線程開始阻塞。後面即便L個線程是讀操作也不可,這裡順序的一緻性。
- 加寫入鎖,當線程T加鎖成功時,其他任何線程都有阻塞,這樣寫鎖獨占
- 線程R加讀鎖,線程W加寫鎖,如果同時到達,那麼寫鎖優先。