[英]Python: Is there a thread safe way to know if lock.acquire() has blocked (and continue blocking)?
我正在为我的REST服务编写API库。 在某些时候,访问令牌将需要更新。 我正在尝试实现一种线程安全的方法来执行此操作,因此即使多个线程可能希望同时更新它,也仅发送一个更新请求。
这是我的代码的简化版本:
import requests
class Api():
def _renew(self):
# send a request which renews token in self._headers
def do_something(self, url, params=None):
r = requests(url, params=params, headers=self._headers)
if r.status_code == 401 and r.json()['error'] == 'Token expired':
# renew the access token
self._renew()
# repeat request with updated headers
r = requests(url, params=params, headers=self._headers)
return r.json()
我需要知道当前的续订请求是否正在进行。 我的想法是这样编写续订功能:
def _renew(self):
lock.acquire()
# i want to check here if the lock.acquire() call blocked
# the thread and return immediately if it has
try:
# send a request to renew token header in self._headers
finally:
lock.release()
我希望其他线程可以调用do_something()
(随后是_renew()
)方法,直到第一个真正更新令牌并使其他人使用它的结果为止。
我怎么知道我的lock.acquire()
调用是否被阻止?
在调用acquire()
lock.locked()
之前检查lock.locked()
的结果不是线程安全的,有时有多个线程向服务器发送更新请求。
您可以调用lock.acquire(False)
进行无阻塞调用,并使用返回值确定是否已获取锁。 看起来像这样:
def _renew(self):
# calling when the lock is already acquired
# will not block and return False
if not lock.acquire(False):
event.wait()
return
# else we acquired the lock
event.clear()
try:
# send a request to renew token header in self._headers
finally:
event.set()
lock.release()
请参阅python 的threading-docs 。
另一种方法是将令牌包装在另一个类中:
from threading import Event, RLock
class Token:
_internal = RLock()
_marker = False
def __init__(self):
# TODO set header
self._header = None
def _renew(self):
# TODO refresh the header
pass
def get(self):
with self._internal:
if self._marker:
self._renew()
self._marker = False
return self._header
# Marks the header to be refreshed at the next get()
def set_renew(self):
with self._internal:
self._marker = True
这具有几个优点。 首先,令牌由自己负责。 在最佳环境中,它只会在需要时刷新自身,而不会被其他类刷新。 这应该在Token#get(self)
。 这也通过将所有get调用包装到锁中来解决线程安全问题,从而防止不必要的修改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.