2009-03-09 2 views
0

어떻게하면 스레드 응용 프로그램에서 조건부 잠금을 구현할 수 있습니까? 예를 들어 함수를 호출하는 스레드가 30 개 있고 모든 스레드가 동시에 액세스 할 수있는 시간은 거의 없지만 함수 입력에 따라 조건이있을 수 있습니다. 하나의 스레드 만이 한 가지 작업을 수행 할 수 있습니다. (입력 값이 반복되고 일부 스레드가 여전히 작동 중이면 잠금이 필요합니다.)파이썬 조건부 잠금

이제 Rlock()을 사용한 모듈 스레딩이 있지만 이제는 설명 된 방식으로 사용하는 방법이 없습니다. 처음 부분에.

편집 : 실제로 두 개의 스레드가 같은 인수를 사용하여 동일한 함수를 동시에 실행하는 것을 방지하는 방법에 대한 질문입니다. (제 질문에 공식적으로 도움을 준 데이비드에게 감사드립니다.)

답변

5

다음을 시도해보십시오. 기능이있는 모듈에 잠금 장치를 달고 기능 입력이 잠금 장치가 필요한 경우, 기능. 그렇지 않으면하지 마십시오.

l = threading.RLock() 

def fn(arg): 
    if arg == arg_that_needs_lock: 
     l.acquire() 
     try: 
      # do stuff 
     finally: 
      l.release() 
    else: 
     # do other stuff 

편집 : 지금까지 내가 지금 말할 수있는

는, 문제는 실제로 같은 시간에 같은 인수와 동일한 기능을 실행 두 스레드를 방지하는 방법에 대한 것입니다 . 두 개의 스레드가 동시에 다른 인수로 같은 함수를 실행해도 문제는 없습니다. 함수가 많은 다른 인수로 호출 할 수있는 경우 있음,하지만,

import threading 

dict_lock = threading.RLock() 
locks = {} 

def fn_dict(arg): 
    dict_lock.acquire() 
    try: 
     if arg not in dict: 
      locks[arg] = threading.RLock() 
     l = locks[arg] 
    finally: 
     dict_lock.release() 
    l.acquire() 
    try: 
     # do stuff 
    finally: 
     l.release() 

: 함수에 유효한 모든 인수가 사전에 키가 될 수있는 경우 간단한 방법은,이 작업을 수행하기 위해 잠금 인수의 사전을 만드는 것입니다 많은 자물쇠가 걸린다. 아마도 더 좋은 방법은 함수가 현재 실행중인 모든 인수 집합을 갖고 해당 집합의 내용을 잠금으로 보호하는 것입니다. 이게 작동해야한다고 생각합니다 :

+0

유일한 문제는 내가 어떤 잠금이 필요하다는 것을 미리 조정 산사 나무의 열매하지 않습니다, 나는 잠이 필요 다른 스레드가 예를 들어 인수 – Ib33X

+0

에 대해 동일한 값을 사용하는 경우에만 대답을 얻을 수 있습니다. 그렇지 않으면 우리는 귀하의 질문이 의미하는 바를 단지 추측합니다 - 당신이 그것을 더 명확하게 편집 할 수 있는지보십시오. 파이썬 2.4에서 –

+1

은 with 문이 없다. – Ib33X

1

Readers-Writer lock과 비슷한 것을 원하는 것처럼 들립니다.

이 당신이 원하는 것을 아마,하지만 단서가 될 수 있습니다

from __future__ import with_statement 
import threading 

def RWLock(readers = 1, writers = 1): 
    m = _Monitor(readers, writers) 
    return (_RWLock(m.r_increment, m.r_decrement), _RWLock(m.w_increment, m.w_decrement)) 

class _RWLock(object): 
    def __init__(self, inc, dec): 
     self.inc = inc 
     self.dec = dec 

    def acquire(self): 
     self.inc() 
    def release(self): 
     self.dec() 
    def __enter__(self): 
     self.inc() 
    def __exit__(self): 
     self.dec() 

class _Monitor(object): 
    def __init__(self, max_readers, max_writers): 
     self.max_readers = max_readers 
     self.max_writers = max_writers 
     self.readers = 0 
     self.writers = 0 
     self.monitor = threading.Condition() 

    def r_increment(self): 
     with self.monitor: 
      while self.writers > 0 and self.readers < self.max_readers: 
       self.monitor.wait() 
      self.readers += 1 
      self.monitor.notify() 

    def r_decrement(self): 
     with self.monitor: 
      while self.writers > 0: 
       self.monitor.wait() 
      assert(self.readers > 0) 
      self.readers -= 1 
      self.monitor.notify() 

    def w_increment(self): 
     with self.monitor: 
      while self.readers > 0 and self.writers < self.max_writers: 
       self.monitor.wait() 
      self.writers += 1 
      self.monitor.notify() 

    def w_decrement(self): 
     with self.monitor: 
      assert(self.writers > 0) 
      self.writers -= 1 
      self.monitor.notify() 

if __name__ == '__main__': 

    rl, wl = RWLock() 
    wl.acquire() 
    wl.release() 
    rl.acquire() 
    rl.release() 

(불행하게도 테스트하지)