2012-04-16 4 views
0

나는 주문형 미러링을 수행하는 간단한 서버를 가지고 있습니다. 가져 오기는 비용이 많이 듭니다 (네트워크 대기 시간, 무결성 검사, (재) 압축 등). 따라서 URL 당 하나의 잠금을 가져오고 싶습니다. 즉,Python 3 - 문자열에 의한 색인 잠금에 의한 경쟁 조건

  • 하나의 스레드 만 하나의 파일을 가져옵니다.
  • 다른 스레드가 현재 페치중인 파일 중 하나를 원하면 파일 준비가 완료 될 때까지 차단됩니다.

내가 처음처럼 뭔가를하고의 생각 :

# Globals 
fetching = dict() 
fetch_lock = threading.Lock() 

... 

lock = None 
do_fetch = False 
with fetch_lock: 
    if url in fetching: 
     lock = fetching[url] 
    else: 
     lock = threading.Lock() 
     fetching[url] = lock 
     do_fetch = True 

# Race condition 
lock.acquire() 

if do_fetch: 
    ... 

with fetch_lock: 
    lock.release() 
    if do_fetch: 
     del fetching[url] 

# Serve file 
... 

경쟁 조건이 (스레드가 캐시에 아직없는 파일에 액세스하려고 할 수 있습니다) 오히려 사소한,하지만 내가 할 수있는 ' 그것을 해결할 방법을 찾지 못한다.

+0

'do_fetch'가 True 인 쓰레드가'lock.acquire()'의 첫 번째 문제가 아닐 수 있습니까? –

+0

정확합니다. --------- – moatPylon

+0

'fetch_lock'을 풀기 전에'lock.acquire()'를 할 수 있습니까? 그러면'lock '을 생성하는 스레드가 먼저 그것을 획득해야합니다. –

답변

1

이 문제를 해결하려면 크리티컬 섹션을 생성하는 중 (중요하지 않은 사람이 없다) 잠금을 잡고 이미 잠금이있는 경우 중요한 섹션 외부에서 획득 할 수 있습니다.

with fetch_lock: 
    if url in fetching: 
     lock = fetching[url] 
    else: 
     lock = threading.Lock() 
     fetching[url] = lock 
     do_fetch = True 
     lock.acquire() 
if not do_fetch: 
    lock.acquire() 

거기서 경쟁 조건이 해결됩니다. 그러나 내가 이해하지 못하는 것은 왜 잠금을 생성하는 스레드가 잠금 테이블에서 스레드를 제거하는지, 그러면 새로운 스레드가 파일을 가져 오는 동안 파일을 처리하는 스레드를 가질 수 있다는 것입니다. 그러나 그것은 당신이 요구 한 것이 아닙니다.

+0

파일을 가져온 후에 후 처리됩니다 , 그래서 점차적으로 그것을 제공 할 수 없습니다. – moatPylon