MST
星途 面试题库

面试题:进程管理之信号量复杂同步场景

在一个具有多个读写进程的系统中,需要实现读者优先的读写锁机制(即多个读者可以同时读,但只要有一个写者在写,其他读写者都不能操作),请使用信号量设计相应的同步方案,并分析该方案在高并发情况下可能出现的问题及解决方案。
43.1万 热度难度
操作系统进程管理

知识考点

AI 面试

面试题答案

一键面试

同步方案

  1. 定义信号量
    • semaphore mutex = 1:用于保护共享资源,确保对readcount的修改是原子操作。
    • semaphore wrt = 1:用于实现写操作的互斥,确保同一时间只有一个写者能进行写操作。
    • int readcount = 0:记录当前正在进行读操作的读者数量。
  2. 读者进程代码
void reader() {
    while (true) {
        // 进入临界区保护readcount
        sem_wait(&mutex);
        readcount++;
        if (readcount == 1) {
            // 第一个读者,阻止写者
            sem_wait(&wrt);
        }
        sem_post(&mutex);
        // 进行读操作
        read();
        // 离开临界区保护readcount
        sem_wait(&mutex);
        readcount--;
        if (readcount == 0) {
            // 最后一个读者,允许写者
            sem_post(&wrt);
        }
        sem_post(&mutex);
    }
}
  1. 写者进程代码
void writer() {
    while (true) {
        // 阻止其他读写者
        sem_wait(&wrt);
        // 进行写操作
        write();
        // 允许其他读写者
        sem_post(&wrt);
    }
}

高并发情况下可能出现的问题

  1. 写者饥饿:由于读者优先,当不断有新的读者到来时,写者可能长时间无法获得wrt信号量,导致写者饥饿。

解决方案

  1. 引入公平机制
    • 可以使用一个计数器来记录等待的写者数量。例如,定义int writecount = 0
    • 读者在获取wrt信号量之前,检查writecount是否为0,如果不为0,则等待。
    • 写者在开始等待wrt信号量之前,先将writecount加1,离开时减1。
  2. 调整信号量获取顺序
    • 可以让读者在获取mutex之后,先检查是否有写者在等待(通过一个标志位或者计数器),如果有写者等待,则读者等待,这样可以避免写者饥饿。例如,定义一个bool write_waiting = false
    • 写者在等待wrt信号量之前,先设置write_waiting = true,获取到wrt信号量后再设置为false
    • 读者在获取mutex后,检查write_waiting,如果为true,则等待(比如通过等待一个新的信号量),直到写者完成操作。