文章目录
读写锁
- 读/写锁(Read-Write Lock)是另外一种避免多个线程同时修改临界资源的一种互斥机制
- 是一种更灵活的同步机制,适用于读多写少的场景
- 允许多个线程同时读取共享资源,但写入时必须独占访问
特点
- 读锁(共享锁):允许多个线程同时获取
- 写锁(独占锁):只允许一个线程获取,且获取时不能有任何读锁或写锁
- 优先级策略:通常写锁优先(防止写线程饿死)
读写锁 vs 互斥锁
| 特性 | 互斥锁 (Mutex) | 读写锁 (RWLock) |
|---|---|---|
| 读操作 | 串行(一次一个线程) | 并行(多个线程可同时读) |
| 写操作 | 串行 | 串行(独占) |
| 适用场景 | 读写频率相当 | 读多写少 |
| 性能 | 一般 | 高并发读时性能更优 |
函数接口
初始化
c
// 静态初始化(全局/静态变量)
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
// 动态初始化(栈/堆变量)
int pthread_rwlock_init(pthread_rwlock_t *rwlock,
const pthread_rwlockattr_t *attr);
加锁操作
c
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); // 获取读锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); // 获取写锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); // 尝试读锁
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); // 尝试写锁
解锁操作
c
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); // 解锁(读/写锁通用)
销毁
c
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
读写锁解决同步问题
c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_READERS 3
#define NUM_WRITERS 2
int balance = 1000;
pthread_rwlock_t rwlock;
void* reader(void* id_ptr) {
int id = *(int*)id_ptr;
while(1) {
pthread_rwlock_rdlock(&rwlock);
printf("读者%d: 查询余额 = %d\n", id, balance);
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
return NULL;
}
void* writer(void* id_ptr) {
int id = *(int*)id_ptr;
while(1) {
int amount = 100;
pthread_rwlock_wrlock(&rwlock);
balance += amount;
printf("写者%d: 存入%d, 新余额 = %d\n", id, amount, balance);
pthread_rwlock_unlock(&rwlock);
sleep(2); // 写操作间隔较长
}
return NULL;
}
int main() {
pthread_t readers[NUM_READERS], writers[NUM_WRITERS];
int r_ids[NUM_READERS], w_ids[NUM_WRITERS];
pthread_rwlock_init(&rwlock, NULL);
// 创建读者
for(int i = 0; i < NUM_READERS; i++) {
r_ids[i] = i + 1;
pthread_create(&readers[i], NULL, reader, &r_ids[i]);
}
// 创建写者
for(int i = 0; i < NUM_WRITERS; i++) {
w_ids[i] = i + 1;
pthread_create(&writers[i], NULL, writer, &w_ids[i]);
}
// 等待(实际上无限循环)
for(int i = 0; i < NUM_READERS; i++) {
pthread_join(readers[i], NULL);
}
pthread_rwlock_destroy(&rwlock);
return 0;
}
latex
时间线:
线程1: R[lock] --- 读操作 --- R[unlock]
线程2: R[lock] --- 读操作 --- R[unlock] ← 可同时读
线程3: W[lock] --- 写操作 --- W[unlock] ← 独占
注意事项
避免死锁
c
// 错误:同一线程内重复加写锁
pthread_rwlock_wrlock(&rwlock);
pthread_rwlock_wrlock(&rwlock); // 死锁
// 正确:解锁后再加锁
pthread_rwlock_wrlock(&rwlock);
// ... 操作
pthread_rwlock_unlock(&rwlock);
pthread_rwlock_wrlock(&rwlock); // 重新获取