读写锁
(1) 读写锁是几把锁
一把锁
pthread_rwlock_t lock;
(2) 读写锁的类型
读锁: 对内存做读操作
写锁: 对内存做写操作
(3) 读写锁的特性:
线程A加读锁成功, 又来了三个线程, 做读操作, 可以加锁成功
读共享, 并行处理
线程A加写锁成功, 又来了三个线程, 做读操作, 三个线程阻塞
写读占, 串行处理
线程A加读锁成功, 又来了B线程加写锁阻塞, 在B之后来了C线程加读锁阻塞
读写不能同时进行
写的优先级高
(4) 读写锁场景练习
线程A加写锁成功, 线程B请求读锁:
线程B阻塞
线程A持有读锁, 线程B请求写锁:
线程B阻塞
线程A拥有读锁, 线程B请求读锁
线程B加锁成功
线程A持有读锁, 然后线程B请求写锁, 然后线程B请求读锁
B阻塞, C阻塞 --> 写的优先级高
A解锁, B线程加写锁成功, C继续阻塞
B解锁, C加读锁成功
线程A持有写锁, 然后线程B请求读锁, 然后线程C请求写锁
B, C阻塞
A解锁, C加写锁, B阻塞
C解锁, B加锁成功
(5) 读写锁使用场景
互斥锁--> 读写串行
读写锁--> 读: 并行; 写: 串行
程序中读操作大于写操作
(6) 主要处理函数
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);
尝试加读锁
加锁成功: 0; 加锁失败: 错误号
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
加写锁
阻塞: 上一次加写锁还没有解锁; 上一次加读锁没解锁
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
尝试加写锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
解锁
(7) 读写锁和互斥锁, 并不是任何时候都能阻塞线程
(8) 练习
3个线程不定时写同一全局资源, 5个线程不定时读同一全局资源
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>
int number = 0;
// 读写锁
pthread_rwlock_t lock;
void *write_func(void *arg) {
while (1) {
pthread_rwlock_wrlock(&lock);
number++;
printf("+++++write: %lu, %d\n", pthread_self(), number);
pthread_rwlock_unlock(&lock);
sleep(1);
}
return NULL;
}
void *read_func(void *arg) {
while (1) {
pthread_rwlock_rdlock(&lock);
printf("======read: %lu, %d\n", pthread_self(), number);
pthread_rwlock_unlock(&lock);
sleep(1);
}
return NULL;
}
int main() {
int i;
pthread_t p[8];
// 初始化读写锁
pthread_rwlock_init(&lock, NULL);
// 3个写线程
for (i = 0; i < 3; i++) {
pthread_create(&p[i], NULL, write_func, NULL);
}
// 5个读线程
for (i = 3; i < 8; i++) {
pthread_create(&p[i], NULL, read_func, NULL);
}
// 回收子线程
for (i = 0; i < 8; i++) {
pthread_join(p[i], NULL);
}
for (i = 0; i < 8; i++) {
pthread_rwlock_destroy(&lock);
}
return 0;
}