面试题答案
一键面试优化方案原理
- 引入公平性机制:为了避免写者饥饿,我们需要引入一种公平性机制。可以使用一个额外的信号量(比如
writeQueue
)来记录写者请求的顺序。 - 调整访问逻辑:当有写者请求访问时,它先获取
writeQueue
信号量,这表示它加入了写者队列。然后,只有当没有其他写者在队列中等待(即writeQueue
信号量计数为0)并且没有写者正在写入(通过writeMutex
信号量控制)时,读者才能开始读取。同样,当写者准备写入时,它需要先获取writeMutex
信号量,确保没有其他写者在写入,同时也需要等待所有读者完成读取(通过readCountMutex
和readCount
控制)。
代码实现(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` 信号量。