Python中是不是有带键的同步锁?
Posted
技术标签:
【中文标题】Python中是不是有带键的同步锁?【英文标题】:Is there a synchronization lock with key in Python?Python中是否有带键的同步锁? 【发布时间】:2021-10-28 00:12:31 【问题描述】:我需要一个 Lock 对象,类似于multiprocessing.Manager().Lock()
只允许从实际获得它的进程中释放。
我的手动实现类似于以下内容:
class KeyLock:
def __init__(self):
self._lock = Lock()
self._key: Optional[str] = None
def acquire(self, key: 'str', blocking: bool = True, timeout: float = 10.0) -> bool:
if self._lock.acquire(blocking=blocking, timeout=timeout):
self._key = key
return True
return False
def release(self, key, raise_error: bool = False) -> bool:
if self._key == key:
self._lock.release()
return True
if raise_error:
raise RuntimeError(
'KeyLock.released called with a non matchin key!'
)
return False
def locked(self):
return self._lock.locked()
要创建此锁的实例并从多个进程中使用它,我将使用自定义管理器类:
class KeyLockManager(BaseManager):
pass
KeyLockManager.register('KeyLock', KeyLock)
manager = KeyLockManager()
manager.start()
lock = manager.KeyLock()
然后我可以从不同的过程中做:
lock.acquire(os.getpid())
# use shared ressource
...
lock.release(os.getpid())
这按预期工作,但对于一项相对简单的任务来说似乎是一项相当大的努力。 所以我想知道是否有更简单的方法可以做到这一点?
【问题讨论】:
如果您可以将 body 转换为函数,我创建了一个可以帮助您的装饰器,请参阅 here 【参考方案1】:有multiprocessing.RLock
,根据定义只能由获取它的进程释放。或者您可能会考虑类似以下的情况,其中 Lock
实例被封装,并且仅用作上下文管理器,除非您已获取它,否则无法释放它,除非您违反封装。当然,可以为类添加额外的保护,以防止尝试违反封装并访问Lock
实例本身。当然,在您的实现中,也可能总是违反封装,因为可以获取其他进程的 pid。所以我们假设所有用户都遵守规则。
from multiprocessing import Lock
class KeyLock:
def __init__(self):
self.__lock = Lock()
def __enter__(self):
self.__lock.acquire()
return None
def __exit__(self, exc_type, exc_val, exc_tb):
self.__lock.release()
return False
# Usage:
key_lock = KeyLock()
with key_lock:
# do something
...
【讨论】:
嗯-谢谢@Booboo。 RLock 根据问题的需要处理锁的所有权。问题是锁将在服务器进程中“活动”,由 Manager() 对象控制。获取锁总是通过代理对象发生,因此锁的所有者可能总是来自服务器进程。 我主张“仅在“with”上下文中使用锁”解决方案。普通锁已经这样做了,除非您不一致,否则我看不出这会如何失败,并且有时会在“with”上下文之外释放锁。确实,使用 RLock 的代理可能不会执行您想要的操作,因为实际的锁对象只存在于一个进程中,而该进程只能继续获取相同的锁。然而,一个普通的 Lock 应该能够完全按照您的要求做,而无需修改。以上是关于Python中是不是有带键的同步锁?的主要内容,如果未能解决你的问题,请参考以下文章