【问题标题】:Python: Building a Reentrant Semaphore (combining RLock and Semaphore)Python:构建可重入信号量(结合 RLock 和信号量)
【发布时间】:2017-03-26 19:41:21
【问题描述】:
您将如何将threading.RLock 与threading.Semaphore 结合起来?还是这样的结构已经存在?
在 Python 中,有一个可重入锁的原语threading.RLock(N),它允许同一个线程多次获取锁,但其他线程不能。还有threading.Semaphore(N),它允许在阻塞之前获取锁N次。如何将这两种结构结合起来?我希望最多 N 单独的线程能够获取锁,但我希望线程上的每个单独的锁都是可重入的。
【问题讨论】:
标签:
python
multithreading
locking
semaphore
【解决方案1】:
所以我猜不存在可重入信号量。这是我想出的实现,很高兴招待 cmets。
import threading
import datetime
class ReentrantSemaphore(object):
'''A counting Semaphore which allows threads to reenter.'''
def __init__(self, value = 1):
self.local = threading.local()
self.sem = threading.Semaphore(value)
def acquire(self):
if not getattr(self.local, 'lock_level', 0):
# We do not yet have the lock, acquire it.
start = datetime.datetime.utcnow()
self.sem.acquire()
end = datetime.datetime.utcnow()
if end - start > datetime.timedelta(seconds = 3):
logging.info("Took %d Sec to lock."%((end - start).total_seconds()))
self.local.lock_time = end
self.local.lock_level = 1
else:
# We already have the lock, just increment it due to the recursive call.
self.local.lock_level += 1
def release(self):
if getattr(self.local, 'lock_level', 0) < 1:
raise Exception("Trying to release a released lock.")
self.local.lock_level -= 1
if self.local.lock_level == 0:
self.sem.release()
__enter__ = acquire
def __exit__(self, t, v, tb):
self.release()