可能原因
- 读操作频繁:大量读操作并发执行,导致写操作长时间等待获取写锁。因为读锁可以共享,只要有读锁存在,写锁就无法获取。
- 死锁:模块之间获取锁的顺序不一致,可能导致死锁,从而写操作一直等待。
- 锁粒度问题:锁的粒度设置不当,如果锁的粒度过大,会导致很多不必要的竞争,写操作等待时间变长。
解决方案
- 读写公平策略
#include <pthread.h>
#include <stdio.h>
// 定义读写锁
pthread_rwlock_t rwlock;
// 定义一个计数器,记录等待写操作的数量
int write_wait_count = 0;
// 自定义读锁获取函数
void custom_read_lock() {
while (write_wait_count > 0) {
// 如果有写操作在等待,读操作等待
sched_yield();
}
pthread_rwlock_rdlock(&rwlock);
}
// 自定义写锁获取函数
void custom_write_lock() {
__sync_fetch_and_add(&write_wait_count, 1);
pthread_rwlock_wrlock(&rwlock);
__sync_fetch_and_sub(&write_wait_count, 1);
}
// 模拟读操作函数
void* read_op(void* arg) {
custom_read_lock();
// 模拟读数据操作
printf("Reading...\n");
pthread_rwlock_unlock(&rwlock);
return NULL;
}
// 模拟写操作函数
void* write_op(void* arg) {
custom_write_lock();
// 模拟写数据操作
printf("Writing...\n");
pthread_rwlock_unlock(&rwlock);
return NULL;
}
- 减小锁粒度
假设原来有一个大的共享数据结构
big_data
用一个读写锁保护,现在将其拆分为多个小的数据结构 small_data1
、small_data2
等,每个小数据结构有自己的读写锁。
#include <pthread.h>
#include <stdio.h>
// 定义两个小的数据结构
struct small_data1 {
int value1;
pthread_rwlock_t rwlock1;
};
struct small_data2 {
int value2;
pthread_rwlock_t rwlock2;
};
struct small_data1 data1 = {1, PTHREAD_RWLOCK_INITIALIZER};
struct small_data2 data2 = {2, PTHREAD_RWLOCK_INITIALIZER};
// 模拟读操作函数,只读取 data1
void* read_op1(void* arg) {
pthread_rwlock_rdlock(&data1.rwlock1);
// 模拟读 data1 数据操作
printf("Reading data1: %d\n", data1.value1);
pthread_rwlock_unlock(&data1.rwlock1);
return NULL;
}
// 模拟写操作函数,只写 data2
void* write_op2(void* arg) {
pthread_rwlock_wrlock(&data2.rwlock2);
// 模拟写 data2 数据操作
data2.value2++;
printf("Writing data2: %d\n", data2.value2);
pthread_rwlock_unlock(&data2.rwlock2);
return NULL;
}
- 定时重试
#include <pthread.h>
#include <stdio.h>
#include <time.h>
// 定义读写锁
pthread_rwlock_t rwlock;
// 模拟写操作函数,使用定时重试
void* write_op(void* arg) {
struct timespec timeout;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += 1; // 1 秒后超时
int ret = pthread_rwlock_timedwrlock(&rwlock, &timeout);
if (ret == ETIMEDOUT) {
printf("Write operation timed out, retry later.\n");
} else if (ret == 0) {
// 模拟写数据操作
printf("Writing...\n");
pthread_rwlock_unlock(&rwlock);
}
return NULL;
}