1、读写锁
与互斥量类似,但读写锁允许更高的并行性。其特性为:写独占,读共享。
读写锁状态:
一把读写锁具备三种状态:
(1)读模式下加锁状态 (读锁)
(2)写模式下加锁状态 (写锁)
(3)不加锁状态
读写锁特性:
-
读写锁是"写模式加锁"时, 解锁前,所有对该锁加锁的线程都会被阻塞。
-
读写锁是"读模式加锁"时, 如果线程以读模式对其加锁会成功;如果线程以写模式加锁会阻塞。
-
读写锁是"读模式加锁"时, 既有试图以写模式加锁的线程,也有试图以读模式加锁的线程。那么读写锁会阻塞随后的读模式锁请求。优先满足写模式锁。读锁、写锁并行阻塞,写锁优先级高
读写锁也叫共享-独占锁。当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的。写独占、读共享。
读写锁非常适合于对数据结构读的次数远大于写的情况。
主要应用函数:
pthread_rwlock_init函数
pthread_rwlock_destroy函数
pthread_rwlock_rdlock函数
pthread_rwlock_wrlock函数
pthread_rwlock_tryrdlock函数
pthread_rwlock_trywrlock函数
pthread_rwlock_unlock函数
以上7 个函数的返回值都是:成功返回0, 失败直接返回错误号。
pthread_rwlock_t类型 用于定义一个读写锁变量。
pthread_rwlock_t rwlock;
pthread_rwlock_init函数
初始化一把读写锁
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
参2:attr表读写锁属性,通常使用默认属性,传NULL即可。
pthread_rwlock_destroy函数
销毁一把读写锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
pthread_rwlock_rdlock函数
以读方式请求读写锁。(常简称为:请求读锁)
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
pthread_rwlock_wrlock函数
以写方式请求读写锁。(常简称为:请求写锁)
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
pthread_rwlock_unlock函数
解锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
pthread_rwlock_tryrdlock函数
非阻塞以读方式请求读写锁(非阻塞请求读锁)
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
pthread_rwlock_trywrlock函数
非阻塞以写方式请求读写锁(非阻塞请求写锁)
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
举例:
1 /************************************************************************* 2 > File Name: pthread_rwlock1.c 3 > Summary: 读写锁示例1 4 > Author: xuelisheng 5 > Created Time: 2018年12月17日 6 ************************************************************************/ 7 8 #include <stdio.h> 9 #include <unistd.h> 10 #include <pthread.h> 11 12 int counter; 13 // 定义全局的读写锁 14 pthread_rwlock_t rwlock; 15 16 // 3个线程不定时调用同一全局资源 17 void *th_write(void *arg) 18 { 19 int t; 20 int i = (int)arg; 21 while(1) 22 { 23 pthread_rwlock_wrlock(&rwlock); // 以写的方式加锁,写独占 24 t = counter; 25 usleep(1000); // 写操作休眠,此时读操作无法获得cpu,即无法进行读操作 26 printf("=====write %d: %lu : counter = %d ++counter = %d ",i, pthread_self(), t, ++counter); 27 pthread_rwlock_unlock(&rwlock); 28 usleep(10000); 29 } 30 return NULL; 31 } 32 33 void *th_read(void *arg) 34 { 35 int i = (int)arg; 36 37 while(1) 38 { 39 pthread_rwlock_rdlock(&rwlock); // 读 读共享 40 printf("------------------------read %d: %lu: %d ", pthread_self(), counter); 41 pthread_rwlock_unlock(&rwlock); 42 usleep(2000); 43 } 44 return NULL; 45 } 46 47 int main() 48 { 49 int i; 50 pthread_t tid[8]; 51 52 // 初始化读写锁(不管多少个读写线程,只需一把读写锁) 53 pthread_rwlock_init(&rwlock, NULL); 54 55 // 循环创建3个写线程 56 for(i = 0; i<3; i++) 57 pthread_create(&tid[i], NULL, th_write, (void *)i); 58 // 循环创建5个读线程 59 for(i = 0; i<5; i++) 60 pthread_create(&tid[i+3], NULL, th_read, (void *)i); 61 62 // 循环回收子线程 63 for(i = 0; i<8; i++) 64 pthread_join(tid[i], NULL); 65 pthread_rwlock_destroy(&rwlock); 66 67 return 0; 68 }
运行输出:
截取部分: ------------------------read 1673803520: 34: 1703023370 ------------------------read 1648625408: 34: 1703023370 ------------------------read 1640232704: 34: 0 =====write 1: 139820055942912 : counter = 34 ++counter = 35 =====write 2: 139820047550208 : counter = 35 ++counter = 36 ------------------------read 1673803520: 36: 0 ------------------------read 1665410816: 36: 0 ------------------------read 1640232704: 36: 0 ------------------------read 1657018112: 36: 1703023370 ------------------------read 1648625408: 36: 0 ------------------------read 1673803520: 36: 0 ------------------------read 1665410816: 36: 0 ------------------------read 1640232704: 36: 0 ------------------------read 1657018112: 36: 0 ------------------------read 1648625408: 36: 0 ------------------------read 1673803520: 36: 0 ------------------------read 1665410816: 36: 0 ------------------------read 1657018112: 36: 3 ------------------------read 1640232704: 36: 2 ------------------------read 1648625408: 36: 1 ------------------------read 1673803520: 36: 0 ------------------------read 1657018112: 36: 1703023370 ------------------------read 1640232704: 36: 1 ------------------------read 1648625408: 36: 2 ------------------------read 1665410816: 36: 1703023370 =====write 0: 139820064335616 : counter = 36 ++counter = 37 ------------------------read 1657018112: 37: 0 ------------------------read 1665410816: 37: 0
观察可知,满足读写锁的特性。