1

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

Да, наверное, мой оригинальный дизайн ослепляя меня к простоте. По-видимому, обычный Lock не может быть слабым. Кроме того, я понимаю, что в наших примерах есть небольшая ошибка - threading.RLock() будет исключен из словаря, потому что мы не сохраняем его как возвращаемое значение из setdefault. Я обновляю основной пост, чтобы больше походить на вас, и принимаю ваш ответ. –

+0

Требуется ли '_mainlock' после того, как' dict.setdefault' был поточно-безопасным в Python 2.7.3 и 3.2.3? – akaihola