读写者问题优化:如何解决Writer过早释放Priority Lock的问题?
问题根源与解决方法
问题分析
当前代码里的Writer拿到priority_lock后立刻释放,导致后续的Reader也能抢到priority_lock,接着Writer和Reader都卡在resource_lock的等待队列里。因为两者等的是同一把锁,原本设计的Writer优先级就失效了——第一个Writer释放resource_lock后,Reader和Writer谁先抢到谁执行,没法保证Writer优先。
最简单的解决方法
让Writer在操作资源的整个周期内持有priority_lock:把priority_lock的释放操作放在resource_lock释放之后。这样一来,只要有Writer在操作资源,priority_lock就会被牢牢占着,其他Writer和Reader都拿不到这把锁,只能排队等。等当前Writer完成资源操作、释放resource_lock后,再释放priority_lock,此时排队的Writer会优先抢到锁,保证Writer的优先级。
修改后的代码
from threading import Thread from threading import Lock from datetime import datetime import time priority_lock = Lock() # 优先级锁 reader_lock = Lock() # 读者计数锁 resource_lock = Lock() # 资源锁 reader_counter = 0 resource = datetime.now().strftime("%H:%M:%S") class Reader(Thread): def run(self): global reader_counter while(True): # 先获取优先级锁,保证没有Writer在排队时才进入 priority_lock.acquire() priority_lock.release() with reader_lock: reader_counter += 1 if reader_counter == 1: resource_lock.acquire() print("Reader: " + resource) with reader_lock: reader_counter -=1 if reader_counter == 0: resource_lock.release() time.sleep(0.1) class ReversedWriter(Thread): def run(self): global resource while True: priority_lock.acquire() # 先拿优先级锁,锁住后续的Reader和Writer resource_lock.acquire() # 再拿资源锁操作资源 resource = datetime.now().strftime("%H:%M:%S") reverse = datetime.now().strftime("%S:%M:%H") print("ReversedWriter " + reverse) resource_lock.release() # 先释放资源锁 priority_lock.release() # 最后释放优先级锁,让后续线程可以抢锁 time.sleep(0.1) class Writer(Thread): def run(self): global resource while True: priority_lock.acquire() # 持有优先级锁直到资源操作完成 resource_lock.acquire() resource = datetime.now().strftime("%H:%M:%S") print("Writer " + resource) resource_lock.release() priority_lock.release() time.sleep(0.1) R1 = Reader() R2 = Reader() R3 = Reader() W1 = Writer() W2 = ReversedWriter() R1.start() R2.start() R3.start() W1.start() W2.start()
逻辑说明
- Writer操作时,先拿
priority_lock再拿resource_lock,直到资源操作完成后才依次释放,期间所有Reader和其他Writer都无法获取priority_lock,也就没法进入资源等待队列,保证了Writer的优先级。 - Reader的逻辑保持不变:必须先拿到
priority_lock才能进入读取流程,确保只有当没有Writer在操作或排队时,Reader才能批量读取资源。
内容的提问来源于stack exchange,提问作者Måns Bodin
相关产品推荐
相关产品推荐

