简体   繁体   中英

Python: Building a Reentrant Semaphore (combining RLock and Semaphore)

How would you go about combining threading.RLock with threading.Semaphore ? Or does such a structure already exist?

In Python, there is a primitive for a Reentrant lock, threading.RLock(N) , which allows the same thread to acquire a lock multiple times, but no other threads can. There is also threading.Semaphore(N) , which allows the lock to be acquired N times before blocking. How would one combine these two structures? I want up to N separate threads to be able to acquire the lock, but I'd like each individual lock on a thread to be a reentrant one.

So I guess a Reentrant semaphore does not exist. Here is the implementation I came up with, happy to entertain comments.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM