1.场景:
现在要读取和写入s3上的文件,为避免读写不一致,须实现一个读写锁,要求如下:
可有多个读线程,写线程只能有一个;
写优先,如果有线程写入,读线程等待。
2.实现方法:
利用python自带的threading库中的threading.Condition()方法,再结合一个计数器。
3. 代码及测试如下:
import threading
class MyReadWriteLock(object):
""" A lock object that allows many simultaneous "read locks", but
only one "write lock." """
def __init__(self):
self._lock = threading.Lock()
self._read_ready = threading.Condition(self._lock)
self._write_ready = threading.Condition(self._lock)
self._writers = 0
def acquire_read(self):
""" Acquire a read lock. Blocks only if a thread has
acquired the write lock. """
with self._read_ready:
if self._writers > 0:
self._read_ready.wait()
def acquire_write(self):
""" Acquire a write lock. Blocks until there are no
acquired write locks. """
with self._write_ready:
self._writers += 1
if self._writers > 1:
self._write_ready.wait()
def release_write(self):
""" Release a write lock. """
with self._write_ready:
self._writers -= 1
if self._writers < 0:
self._writers = 0
if not self._writers:
self._read_ready.notifyAll()
self._write_ready.notify()
if __name__ == '__main__':
import time
rwl = MyReadWriteLock()
class Writer(threading.Thread):
def run(self):
print self, 'start'
rwl.acquire_write()
print self, 'acquired'
time.sleep(5)
print self, 'stop'
rwl.release_write()
class Reader(threading.Thread):
def run(self):
print self, 'start'
rwl.acquire_read()
print self, 'acquired'
time.sleep(3)
print self, 'stop'
class Reader1(threading.Thread):
def run(self):
print self, 'start'
rwl.acquire_read()
print self, 'acquired'
time.sleep(3)
print self, 'stop'
class Writer1(threading.Thread):
def run(self):
print self, 'start'
rwl.acquire_write()
print self, 'acquired'
time.sleep(5)
print self, 'stop'
rwl.release_write()
Writer().start()
time.sleep(1)
Reader().start()
time.sleep(1)
Reader1().start()
time.sleep(1)
Writer1().start()
4. 实现细节:
- self._read_ready和write_ready分别等在各自的condition上,但是共用同一把锁。
- 只有在写的计数器self._writers = 0时,才释放所有的读线程
参考链接:Allowing Multithreaded Read Access While Maintaining a Write Lock