并发编程经典问题之读者写着。本文简单介绍了问题模型,并提供了一种 Python3 的解决方式。
问题模型
-
问题描述,有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误,因此要求:
- 允许多个读者可同时对文件执行读操作
- 只允许一个写者往文件中写信息
- 任一写者在完成写操作之前不允许其他读者或写者工作
- 写者执行写操作前,应让已有的写者和读者全部退出
-
问题分析,读写兼容性情况:
兼容性 | 请求读 | 请求写 |
---|---|---|
当前读 | 兼容 | 不兼容 |
当前写 | 不兼容 | 不兼容 |
Talk is cheap, show me code
- 读优先,读线程可以插队,可能会出现写线程饿死
- 读写均衡,读写线程公平竞争
from threading import Lock
# 读优先
class IOReadPre():
l_count = None
l_w = None
count = 0
def __init__(self, fname):
self.l_count = Lock()
self.l_w = Lock()
self.count = 0
def readline(self, offset):
self.l_count.acquire()
if self.count == 0: # 当第一个读进程读共享文件时
self.l_w.acquire() # 阻止写进程写
self.count += 1 # 读计数器加一
self.l_count.release()
# 读操作
...your code...
self.l_count.acquire()
self.count -= 1 # 读计数器减一
if self.count == 0: # 当最后一个读进程读完共享文件
self.l_w.release() # 允许写进程写
self.l_count.release()
return data, offset
def append(self, data):
self.l_w.acquire()
# 写操作
...your code...
self.l_w.release()
# 读写均衡
class IOBalance():
l_count = None
l_rw = None
l_w = None
count = 0
def __init__(self, fname):
self.l_count = Lock()
self.l_rw = Lock()
self.l_w = Lock()
self.count = 0
def readline(self, offset):
self.l_rw.acquire() # 为了读写公平,加一个锁,写进程先拿到的话,就会阻塞后面的读
self.l_count.acquire()
if self.count == 0: # 当第一个读进程读共享文件时
self.l_w.acquire() # 阻止写进程写
self.count += 1 # 读计数器加一
self.l_count.release()
self.l_rw.release()
# 读操作
...your code...
self.l_count.acquire()
self.count -= 1 # 读计数器减一
if self.count == 0: # 当最后一个读进程读完共享文件
self.l_w.release() # 允许写进程写
self.l_count.release()
return data, offset
def append(self, data):
self.l_rw.acquire()
self.l_w.acquire()
# 写操作
...your code...
self.l_w.release()
self.l_rw.release()