续接上一篇“线程同步”:https://cloud.tencent.com/developer/article/1629556
本文讲述读写锁。读写锁和互斥量不太一样,它允许锁可以是读加锁,写加锁以及未加锁三种状态。每次只能由一个线程处于写加锁状态,但是可以有多个线程处于读加锁状态。
读写锁是一把锁,不是两把锁。它就像是多路开关一样。当锁处于写加锁状态时,所有其他试图对这个锁进行读加锁或者写加锁的线程都会被阻塞;当锁处于读加锁状态时,所有试图对这个锁进行读加锁的线程头可以得到访问权,而所有试图对这个锁进行写加锁的线程都会被阻塞。
读写锁很明显带来了比互斥量更高的并发性。并且读写锁非常适合读取比写入操作更多的情况。有的教材会把读写锁也称为“共享互斥锁”。当读写锁以写模式锁住,称之为“共享模式锁住”;而当读写锁以读模式锁住,称之为“互斥模式锁住”。
下面是供我们在POSIX下进行读写锁初始化和反向初始化的函数。
下面是与写加锁的函数。
下面是与读加锁的函数。
由于读写锁是一把锁,因此在解锁的时候无论你是读加锁,还是写加锁,都是使用下面的解锁函数。
代码语言:javascript复制#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
char str[30]; //共享资源
pthread_rwlock_t rwlock; //读写锁
void *th_write(void *arg)
{
usleep(300); //延时
pthread_rwlock_wrlock(&rwlock);
strcpy(str,"123");
pthread_rwlock_unlock(&rwlock);
pthread_exit(NULL);
}
void *th_read(void *arg)
{
pthread_rwlock_rdlock(&rwlock);
printf("read: %sn",str);
pthread_rwlock_unlock(&rwlock);
pthread_exit(NULL);
}
int main(void)
{
int i;
pthread_t tid[8];
strcpy(str,"Hello World!");
pthread_rwlock_init(&rwlock, NULL); //初始化锁
for (i = 0; i<3; i ) //3和写线程
pthread_create(&tid[i], NULL, th_write, NULL);
for (i = 0; i<5; i ) //5个读线程
pthread_create(&tid[i 3], NULL, th_read, NULL);
for (i = 0; i<8; i ) //等待线程结束,回收线程
pthread_join(tid[i], NULL);
pthread_rwlock_destroy(&rwlock); //销毁锁
return 0;
}
运行结果如下:
可以看到,可以多个读线程去访问读加锁的资源。并且写加锁只能被某个线程独自访问。其余线程都在阻塞。并且等待线程中的写加锁线程比读加锁线程优先级高。
总结一下:
读共享,写独享;写必读优先级高。