Является ли этот код потокобезопасным в Python 2.7?

Должен ли я использовать атомный счетчик с блокировкой или это можно использовать?

 def somefunc(someparam):
     if someparam:
        dic['key'] +=1

2 ответа

Решение

Нет, ваш код не является потокобезопасным, потому что использование += расширенное присваивание значения в словаре требует 3 кода операции для выполнения:

>>> dis.dis(compile("dic['key'] += 1", '', 'exec'))
  1           0 LOAD_NAME                0 (dic)
              3 LOAD_CONST               0 ('key')
              6 DUP_TOPX                 2
              9 BINARY_SUBSCR
             10 LOAD_CONST               1 (1)
             13 INPLACE_ADD
             14 ROT_THREE
             15 STORE_SUBSCR
             16 LOAD_CONST               2 (None)
             19 RETURN_VALUE

Код операции в позиции 9, BINARY_SUBSCR извлекает текущее значение из словаря Где-нибудь между кодами операций 9 и 15 (где STORE_SUBSCR возвращает значение обратно), может произойти переключение потока, и другой поток может обновить словарь.

Встроенные структуры Python являются потокобезопасными для отдельных операций. GIL (глобальная блокировка интерпретатора) заботится об этом. Но в основном трудно понять, где оператор становится больше операций.

Добавление блокировки даст вам душевное спокойствие:

def somefunc(someparam):
    if someparam:
        with lock:
            dic['key'] +=1
Другие вопросы по тегам