2016-11-12 2 views
0

threading.RLockthreading.Semaphore과 어떻게 조합 하시겠습니까? 아니면 그런 구조가 이미 존재합니까?Python : Reentrant Semaphore 빌드하기 (RLock과 Semaphore 결합)

파이썬에는 재진입 식 잠금 threading.RLock(N)에 대한 프리미티브가 있습니다. threading.RLock(N)은 같은 스레드가 여러 번 잠금을 획득 할 수 있지만 다른 스레드는 수 없도록합니다. 차단하기 전에 잠금을 N 번 획득 할 수있는 threading.Semaphore(N)도 있습니다. 어떻게이 두 구조를 결합 할 수 있습니까? 내가 최대 N 별도의 스레드가 잠금을 획득 할 수 싶지만 스레드에 대한 각각의 개별 잠금 재진입 싶습니다.

답변

0

그래서 Reentrant 세마포어가 존재하지 않는다고 생각합니다. 다음은 내가 생각해 낸 구현이며, 논평을 즐겁게 해줍니다.

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