相当于Java同步的Python



在Java中,只需添加synchronized关键字就可以使变量线程安全。在Python中有什么可以达到同样的结果吗?

您可以使用with self.lock:,然后将代码放入其中。看见http://theorangeduck.com/page/synchronized-python了解更多信息。

使用with self.lock的工作代码,如果发生,可以处理exception

Manager内部,我们正在使Manager方法线程安全:

from threading import RLock

class Manager:
def __init__(self):
self.lock = RLock()
self.hash: dict[str, int] = dict()
def containsToken(self, key) -> bool:
with self.lock:
self.lock.acquire()
return key in self.hash

def addToken(self, token: str):
with self.lock:
token = token.strip()
if token in self.hash:
self.hash[token] = self.hash[token] + 1
else:
self.hash[token] = 1

def removeToken(self, token):
with self.lock:
if token not in self.hash:
raise KeyError(f"token : {token} doesn't exits")
self.hash[token] = self.hash[token] - 1
if self.hash[token] == 0:
self.hash.pop(token)
if __name__ == "__main__":
sync = Manager()
sync.addToken("a")
sync.addToken("a")
sync.addToken("a")
sync.addToken("a")
sync.addToken("B")
sync.addToken("B")
sync.addToken("B")
sync.addToken("B")
sync.removeToken("a")
sync.removeToken("a")
sync.removeToken("a")
sync.removeToken("B")
print(sync.hash)

输出:

{'a': 1, 'B': 3}

您可以编写自己的@synchronized装饰器。

该示例使用互斥锁:

from functools import wraps
from multiprocessing import Lock

def synchronized(member):
"""
@synchronized decorator.
Lock a method for synchronized access only. The lock is stored to
the function or class instance, depending on what is available.
"""
@wraps(member)
def wrapper(*args, **kwargs):
lock = vars(member).get("_synchronized_lock", None)
result = ""
try:
if lock is None:
lock = vars(member).setdefault("_synchronized_lock", Lock())
lock.acquire()
result = member(*args, **kwargs)
lock.release()
except Exception as e:
lock.release()
raise e
return result
return wrapper

现在你可以装饰这样的方法:

class MyClass:
...
@synchronized
def hello_world(self):
print("synced hello world")

还有一篇关于丢失的同步装饰器的优秀博客文章。

最新更新