MST
星途 面试题库

面试题:并发与同步:信号量在读者 - 写者问题中的优化应用

在经典的读者 - 写者问题中,读者可以同时读取数据,但写者需要独占访问数据。如果使用信号量解决此问题,在高并发场景下,可能会出现写者饥饿的情况。请提出一种基于信号量的优化方案来避免写者饥饿,并详细阐述方案原理,同时用代码(你熟悉的编程语言)实现该优化方案。
18.9万 热度难度
操作系统并发与同步

知识考点

AI 面试

面试题答案

一键面试

优化方案原理

  1. 引入公平性机制:为了避免写者饥饿,我们需要引入一种公平性机制。可以使用一个额外的信号量(比如 writeQueue)来记录写者请求的顺序。
  2. 调整访问逻辑:当有写者请求访问时,它先获取 writeQueue 信号量,这表示它加入了写者队列。然后,只有当没有其他写者在队列中等待(即 writeQueue 信号量计数为0)并且没有写者正在写入(通过 writeMutex 信号量控制)时,读者才能开始读取。同样,当写者准备写入时,它需要先获取 writeMutex 信号量,确保没有其他写者在写入,同时也需要等待所有读者完成读取(通过 readCountMutexreadCount 控制)。

代码实现(Python + Semaphore)

import threading


class RWLock:
    def __init__(self):
        self.readCount = 0
        self.readCountMutex = threading.Semaphore(1)
        self.writeMutex = threading.Semaphore(1)
        self.writeQueue = threading.Semaphore(1)


    def reader_acquire(self):
        self.writeQueue.acquire()
        self.readCountMutex.acquire()
        self.readCount += 1
        if self.readCount == 1:
            self.writeMutex.acquire()
        self.readCountMutex.release()
        self.writeQueue.release()


    def reader_release(self):
        self.readCountMutex.acquire()
        self.readCount -= 1
        if self.readCount == 0:
            self.writeMutex.release()
        self.readCountMutex.release()


    def writer_acquire(self):
        self.writeQueue.acquire()
        self.writeMutex.acquire()


    def writer_release(self):
        self.writeMutex.release()
        self.writeQueue.release()


测试代码

rw_lock = RWLock()

def reader(id): rw_lock.reader_acquire() print(f"Reader {id} is reading") rw_lock.reader_release()

def writer(id): rw_lock.writer_acquire() print(f"Writer {id} is writing") rw_lock.writer_release()

创建一些读者和写者线程

readers = [threading.Thread(target=reader, args=(i,)) for i in range(3)] writers = [threading.Thread(target=writer, args=(i,)) for i in range(3)]

启动线程

for r in readers: r.start() for w in writers: w.start()

等待所有线程完成

for r in readers: r.join() for w in writers: w.join()


在上述代码中:
 - `RWLock` 类封装了读写锁的逻辑。
 - `reader_acquire` 方法中,读者先获取 `writeQueue` 信号量,检查 `readCount` 并在必要时获取 `writeMutex` 信号量,确保没有写者在写入。
 - `reader_release` 方法减少 `readCount` 并在 `readCount` 为0时释放 `writeMutex` 信号量。
 - `writer_acquire` 方法中,写者先获取 `writeQueue` 信号量,然后获取 `writeMutex` 信号量,确保独占访问。
 - `writer_release` 方法释放 `writeMutex` 和 `writeQueue` 信号量。