MST
星途 面试题库

面试题:C语言读写锁在复杂场景下的问题与解决

在一个大型C语言项目中,存在多个模块共享数据并使用读写锁进行并发控制。偶尔会出现写操作长时间等待的情况,分析可能导致这种情况的原因,并使用C语言提出至少两种有效的解决方案。
13.1万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

可能原因

  1. 读操作频繁:大量读操作并发执行,导致写操作长时间等待获取写锁。因为读锁可以共享,只要有读锁存在,写锁就无法获取。
  2. 死锁:模块之间获取锁的顺序不一致,可能导致死锁,从而写操作一直等待。
  3. 锁粒度问题:锁的粒度设置不当,如果锁的粒度过大,会导致很多不必要的竞争,写操作等待时间变长。

解决方案

  1. 读写公平策略
#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;
}
  1. 减小锁粒度 假设原来有一个大的共享数据结构 big_data 用一个读写锁保护,现在将其拆分为多个小的数据结构 small_data1small_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;
}
  1. 定时重试
#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;
}