2012-04-16 38 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()'? – 2012-04-16 17:43:25

+0

準確。 --------- – moatPylon 2012-04-16 17:46:47

+0

你可以在釋放'fetch_lock'之前做'lock.acquire()'嗎?然後,創建'lock'的線程必須是第一個獲取它的線程。 – 2012-04-16 17:48:56

回答

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 2012-04-16 17:55:33