1
import threading 
import weakref 
_mainlock = threading.RLock() 
_job_locks = weakref.WeakValueDictionary() 
def do_thing(job_id): 
    _mainlock.acquire() #Dictionary modification lock acquire 
    _job_locks.setdefault(job_id, threading.RLock()) #Possibly modifies the dictionary 
    _mainlock.release() 
    _job_locks[job_id].acquire() 
    try: 
     one_time_init(job_id) 
    finally: 
     _job_locks[job_id].release() 
    #On function return, the weakref.WeakValueDictionary should cause the key to evaporate 

假設do_thing()在許多線程上被調用很多次,其ID號可能相同也可能不相同(例如,ID 3爲4次,ID爲1次),這個線程是否安全? one_time_init()會一次爲特定作業ID運行多次? (PS:one_time_init保存它的狀態是已經爲每個ID運行一次,因此調用它,如果它已經運行到完成無操作)Python:使用短命鍵的線程安全字典,這是正確的嗎?


更新後的代碼(感謝THC4k):

import threading 
import weakref 
_mainlock = threading.RLock() 
_job_locks = weakref.WeakValueDictionary() 

def do_thing(job_id): 
    with _mainlock: 
     jl = _job_locks.setdefault(job_id, threading.RLock()) 
    with jl: 
     one_time_init(job_id) 

回答

3

好像安全。爲什麼你甚至需要_job_locks如果one_time_init再次檢查它是否運行?你可以在那裏添加鎖。爲什麼RLock而不是Lock(該函數似乎永遠不會重新輸入)?

不管怎麼說,在with語句如下方式更好:

import threading 
import weakref 
_mainlock = threading.RLock() 
_job_locks = weakref.WeakValueDictionary() 

def do_thing(job_id): 
    with _mainlock: 
     _job_locks.setdefault(job_id, threading.RLock()) 
    with _job_locks[job_id]: 
     one_time_init(job_id) 
+0

呀,可能是我原來的設計致盲我簡單。顯然一個普通的鎖不能被弱反射。另外,我意識到我們的例子中有一個小錯誤 - threading.RLock()將從字典中刪除,因爲我們沒有將它作爲setdefault的返回值存儲。我會更新主帖,看起來更像你的,並接受你的回答。 – 2010-07-23 17:30:13

+0

在Python 2.7.3和3.2.3中將dict.setdefault設爲線程安全後仍然需要'_mainlock'? – akaihola 2017-05-26 04:01:11