Created
January 17, 2020 13:13
-
-
Save stoensin/dab2d8dd3825f8f38d4605f65ae50acc to your computer and use it in GitHub Desktop.
提高并发的演进思路,就在: 普通锁,本质是串行执行 读写锁,可以实现读读并发 数据多版本,可以实现读写并发 读写锁相对于单纯的互斥锁,适用性更高,可以多个线程同时占用读模式的读写锁,但是只能一个线程占用写模式的读写锁。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class RWLock(object): | |
def __init__(self): | |
self.lock = threading.Lock() | |
self.rcond = threading.Condition(self.lock) | |
self.wcond = threading.Condition(self.lock) | |
self.read_waiter = 0 # 等待获取读锁的线程数 | |
self.write_waiter = 0 # 等待获取写锁的线程数 | |
self.state = 0 # 正数:表示正在读操作的线程数 负数:表示正在写操作的线程数(最多-1) | |
self.owners = [] # 正在操作的线程id集合 | |
self.write_first = True # 默认写优先,False表示读优先 | |
def write_acquire(self, blocking=True): | |
# 获取写锁只有当 | |
me = threading.get_ident() | |
with self.lock: | |
while not self._write_acquire(me): | |
if not blocking: | |
return False | |
self.write_waiter += 1 | |
self.wcond.wait() | |
self.write_waiter -= 1 | |
return True | |
def _write_acquire(self, me): | |
# 获取写锁只有当锁没人占用,或者当前线程已经占用 | |
if self.state == 0 or (self.state < 0 and me in self.owners): | |
self.state -= 1 | |
self.owners.append(me) | |
return True | |
if self.state > 0 and me in self.owners: | |
raise RuntimeError('cannot recursively wrlock a rdlocked lock') | |
return False | |
def read_acquire(self, blocking=True): | |
me = threading.get_ident() | |
with self.lock: | |
while not self._read_acquire(me): | |
if not blocking: | |
return False | |
self.read_waiter += 1 | |
self.rcond.wait() | |
self.read_waiter -= 1 | |
return True | |
def _read_acquire(self, me): | |
if self.state < 0: | |
# 如果锁被写锁占用 | |
return False | |
if not self.write_waiter: | |
ok = True | |
else: | |
ok = me in self.owners | |
if ok or not self.write_first: | |
self.state += 1 | |
self.owners.append(me) | |
return True | |
return False | |
def unlock(self): | |
me = threading.get_ident() | |
with self.lock: | |
try: | |
self.owners.remove(me) | |
except ValueError: | |
raise RuntimeError('cannot release un-acquired lock') | |
if self.state > 0: | |
self.state -= 1 | |
else: | |
self.state += 1 | |
if not self.state: | |
if self.write_waiter and self.write_first: # 如果有写操作在等待(默认写优先) | |
self.wcond.notify() | |
elif self.read_waiter: | |
self.rcond.notify_all() | |
elif self.write_waiter: | |
self.wcond.notify() | |
read_release = unlock | |
write_release = unlock |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment