目录
1.概念
读写锁实际上是一种特殊的自旋锁,它把共享资源的访问划分成读者和写者,读者只能拥有对共享资源的读权限,写者则需要对共享资源进行写操作。读写锁并不是两把锁,它是一个名字叫做读写锁的锁,可以拥有读模式下加锁状态,写模式下加锁状态和不加锁者三种状态。它与互斥量类似,对比互斥量,使用读写锁可以使得运行有更高的并行性。
2.读写锁的状态
a.读模式下加锁状态(读锁)
b.写模式下加锁状态(写锁)
c.不加锁状态
3.读写锁特性
精炼概括:写独占,读共享。
更具体点可如下:
1.读写锁是“写模式加锁”时(写锁),解锁前,所有对该锁加锁的线程都会被阻塞;
2.读写锁是“读模式加锁”时(读锁),如果T1中读锁已经加锁成功了,此时来了三个其他线程,分情况讨论:
T1以读模式加锁成功,T2,T3,T4都请求写锁,T2,T3,T4都会阻塞,后续写锁自由竞争;
T1以读模式加锁成功,T2请求写,T3和T4请求读,此时T2,T3,T4都会被阻塞,但是等待T1完成读释放锁之后,优先满足写线程T2,之后满足T3和T4的读请求,因为写锁请求的T2的优先级高.
T1以读模式加锁成功,T2,T3,T4都请求读锁,可共享去读。
4.读写锁的适用场景
读写锁非常适合于对数据结构读的次数远远大于写的情况。
5.主要数据类型和应用函数
读写锁变量 | 实例 |
pthread_rwlock_t | pthread_rwlock_t rwlock(定义了一个读写锁变量rwlock) |
头文件:
#include <pthread.h>
函数体:
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
返回值:
以上共7个函数的返回值在成功情况下都返回0,失败的时候i返回int类型的错误号。
6.编码举例
/*
作者:Muten
编码日期:20201016
代码功能:三个写线程对全局共享资源变量进行读操作,五个读线程对全局共享资源变量进行读操作
编码目的:演示读写锁的使用
运行环境:
Linux localhost.localdomain 3.10.0-957.el7.x86_64 #1 SMP Thu Nov 8 23:39:32 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
*/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int counter; // 定义全局共享资源变量
pthread_rwlock_t rwlock;// 定义全局读写锁变量
// 写线程
void *th_write(void* arg)
{
int t;
int i = (int) arg;
while(1)
{
t = counter;
usleep(1000);
pthread_rwlock_wrlock(&rwlock);
printf("**********************************************write thread %d: %lu : counter = %d, ++counter = %d\n",i,pthread_self(),t,++counter);
pthread_rwlock_unlock(&rwlock);
usleep(5000);
}
return NULL;
}
// 读线程
void *th_read(void* arg)
{
int i = (int) arg;
while(1)
{
pthread_rwlock_rdlock(&rwlock);
printf("read thread %d: %lu : counter = %d\n",i,pthread_self(),counter);
pthread_rwlock_unlock(&rwlock);
usleep(900);
}
return NULL;
}
int main()
{
int i ;
pthread_t tid[8];
pthread_rwlock_init(&rwlock,NULL);
for(i = 0;i<3;i++)
pthread_create(&tid[i],NULL,th_write,(void*)i);
for(i = 0;i<5;i++)
pthread_create(&tid[i+5],NULL,th_read,(void*)i);
for(i = 0;i<8;i++)
pthread_join(tid[i],NULL);
pthread_rwlock_destroy(&rwlock);
return 0;
}