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

时间:2016-11-12 20:18:17

标签: python multithreading locking semaphore

您如何将threading.RLockthreading.Semaphore合并?或者这种结构是否已经存在?

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

1 个答案:

答案 0 :(得分:1)

所以我猜一个重入的信号量不存在。这是我提出的实现,很高兴收到评论。

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()