Python:构建可重入信号量(结合RLock和信号量)

Python:构建可重入信号量(结合RLock和信号量),python,multithreading,locking,semaphore,Python,Multithreading,Locking,Semaphore,如何将threading.RLock与threading.Semaphore相结合?或者这样的结构已经存在 在Python中,有一个可重入锁的原语,threading.RLock(N),它允许同一线程多次获取锁,但其他线程不能。还有threading.Semaphore(N),它允许在阻塞前N次获取锁。如何将这两种结构结合起来?我希望多达N个独立的线程能够获得锁,但我希望线程上的每个单独的锁都是可重入的。所以我猜不存在可重入的信号量。下面是我提出的实施方案,很高兴接受评论 import thre

如何将
threading.RLock
threading.Semaphore
相结合?或者这样的结构已经存在


在Python中,有一个可重入锁的原语,
threading.RLock(N)
,它允许同一线程多次获取锁,但其他线程不能。还有
threading.Semaphore(N)
,它允许在阻塞前
N
次获取锁。如何将这两种结构结合起来?我希望多达
N
个独立的线程能够获得锁,但我希望线程上的每个单独的锁都是可重入的。

所以我猜不存在可重入的信号量。下面是我提出的实施方案,很高兴接受评论

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()
导入线程
导入日期时间
类ReentrantSemaphore(对象):
''一个允许线程重新进入的计数信号''
def uuu init uuuu(self,value=1):
self.local=threading.local()
self.sem=threading.Semaphore(值)
def获取(自我):
如果不是getattr(self.local,'lock_level',0):
#我们还没有锁,去拿吧。
start=datetime.datetime.utcnow()
self.sem.acquire()
end=datetime.datetime.utcnow()
如果end-start>datetime.timedelta(秒=3):
logging.info(“锁定花费了%d秒。”%((结束-开始).total_seconds())
self.local.lock\u time=结束
self.local.lock_level=1
其他:
#我们已经有了锁,只是由于递归调用而增加了它。
self.local.lock_级别+=1
def释放(自):
如果getattr(self.local,'lock_level',0)<1:
引发异常(“尝试释放已释放的锁”)
self.local.lock_level-=1
如果self.local.lock_level==0:
self.sem.release()
__输入\获取
定义退出(自身、t、v、tb):
self.release()