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 () вызывается много раз во многих потоках с номерами идентификаторов, которые могут совпадать или не совпадать (скажем, 4 раза с идентификатором 3 и один раз с разными идентификаторами), безопасен ли этот поток?Будет ли one_time_init () запускаться более одного раза для определенного идентификатора задания за раз?(PS: one_time_init сохраняет свое состояние, которое было выполнено один раз для каждого идентификатора, поэтому, если он уже завершен, вызов его не работает)
Обновленный код (спасибо 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)