Является ли сборщик.defaultdict потокобезопасным?

Я вообще не работал с потоками в Python и задавал этот вопрос как совершенно незнакомый.

Мне интересно, если defaultdict является потокобезопасным. Позвольте мне объяснить это:

у меня есть

 d = defaultdict(list) 

который по умолчанию создает список отсутствующих ключей. Предположим, что несколько потоков начали делать это одновременно:

 d['key'].append('value') 

В конце концов, я должен закончить с помощью ['value', 'value'] . Однако, если defaultdict не является потокобезопасным, если поток 1 defaultdict поток 2 после проверки if 'key' in dict и до d['key'] = default_factory() , это вызовет чередование, а другой поток будет создать список в d['key'] и добавить 'value' .

Затем, когда поток 1 выполняется снова, он будет продолжаться с d['key'] = default_factory() который уничтожит существующий список и значение, и мы закончим в ['key'] .

Я посмотрел исходный код CPython для defaultdict . Однако я не мог найти никаких замков или мьютексов. Я предполагаю, что он не является потокобезопасным, если он документирован так.

Некоторые ребята вчера вечером в IRC сказали, что на Python есть GIL, поэтому он концептуально потокобезопасен. Некоторые упомянутые потоки не должны выполняться в Python. Я довольно смущен. Идеи?

    One Solution collect form web for “Является ли сборщик.defaultdict потокобезопасным?”

    В этом конкретном случае он является потокобезопасным.

    Чтобы узнать, почему важно понимать, когда Python переключает потоки. CPython позволяет переключаться между потоками между шагами байт-кода Python. Именно здесь прибывает GIL; каждая инструкция по N-байтовому коду освобождает блокировку и может иметь переключатель потоков.

    Код d['key'] обрабатывается одним BINARY_SUBSCR кодом ( BINARY_SUBSCR ), который запускает метод .__getitem__() для .__getitem__() в словаре.

    defaultdict , настроенный со list в качестве фабрики значений по умолчанию, обрабатывает метод dict.__getitem__() целиком на C, и GIL никогда не разблокируется, что делает dict[key] lookups thread safe.

    Обратите внимание на квалификацию; если вы создаете экземпляр defaultdict с другим заводским значением по умолчанию, например, который использует код Python (например, lambda: [1, 2, 3] ), все ставки отключены, так как это означает, что C-код перезвонит в код Python и GIL может быть снова выпущен при выполнении байт-кода для функции lambda . Аналогичным образом, если завод написан на C-коде, который явно освобождает GIL, может произойти переключение потоков, и безопасность потока выходит из окна.

    Python - лучший язык программирования в мире.