В python у меня есть глобальная переменная, которая получает чтение/приращение различными потоками. Из-за GIL это может вызвать проблемы без использования каких-либо механизмов блокировки?Python GIL и globals
ответ
Да, многопоточность без блокировки почти всегда вызывает проблемы, с или без GIL.
Обратите внимание, что GIL не существует для защиты ваших данных приложения; это только для защиты некоторых внутренних структур Python, таких как подсчет ссылок для объектов Python. Вы все равно должны заблокировать свои структуры. –
Точно. GIL защищает Python от себя, но он не делает ничего, чтобы защитить вас. –
И, конечно, подавляющее большинство двигателей исполнения Python даже не имеют * GIL. –
В GIL требуется, чтобы интерпретатор полностью выполнял одну инструкцию по байт-коду перед тем, как другой поток может взять верх. Однако нет оснований предполагать, что операция приращения является одной инструкцией. Например:
>>> import dis
>>> dis.dis(compile("x=753","","exec"))
1 0 LOAD_CONST 0 (753)
3 STORE_NAME 0 (x)
6 LOAD_CONST 1 (None)
9 RETURN_VALUE
>>> dis.dis(compile("x+=1","","exec"))
1 0 LOAD_NAME 0 (x)
3 LOAD_CONST 0 (1)
6 INPLACE_ADD
7 STORE_NAME 0 (x)
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
Как вы можете видеть, даже эти простые операции являются более чем одной инструкцией байткода. Поэтому, когда вы используете обмен данными между потоками, вы должны использовать с помощью отдельного механизма блокировки (например, threading.lock) для обеспечения согласованности данных.
Ouch. Я имею в виду, 3 upvotes и никто не заметил вывод 'dis.dis (« x = 753 »)'? Я исправил код. – tzot
Вот пример, где я должен уделять больше внимания тому, что я пишу - спасибо :). Кроме того, он отображает точку еще более четко - после загрузки значения есть несколько инструкций до того, как значение будет сохранено снова. –
это даже не 100% правда. Байт-код (почти любой) может фактически вызвать больше кода на основе python, используя '__getitem__' или' __add__' или любой другой сценарий. Затем вы заканчиваете тем, что потоки меняются в середине через один байт-код. – fijal
Вы говорите о реализации с использованием модуля «threading»? В этом случае вы должны использовать предоставленный механизм блокировки: см. Http://docs.python.org/library/threading.html – avpx