Блокировка свободной реализации стека в Python
Можно ли реализовать стек без блокировки в Python? Я искал в Интернете и не нашел функцию CAS в Python.
1 ответ
Вы упомянули CAS и атомарные операции в отдельности, но стандартная реализация Python(CPython) работает с байтовым кодом и использует также так называемую глобальную блокировку интерпретатора. Итак, вот несколько выводов, почему в Python нет атомарных операций и почему в этом нет необходимости.
Глобальная блокировка интерпретатора ( GIL)
В CPython глобальная блокировка интерпретатора, или GIL, является мьютексом, который не позволяет нескольким собственным потокам одновременно выполнять байт-коды Python.
Это означает, что только один поток одновременно может выполнять Python. Когда несколько потоков работают, они вращаются в своем исполнении. Потоки могут освобождать gil только между инструкциями байт-кода - поэтому не в середине выполненной инструкции. Каждая инструкция уже "атомарна" с точки зрения программы на Python. Но не смешивайте это с аппаратными атомарными операциями на ЦП, это уровень глубже. За каждой инструкцией байт-кода есть несколько инструкций ассемблера, которые выполняются.
Атомарные операции необходимы только тогда, когда вы хотите, чтобы такая операция, как сравнение и переключение, не прерывалась никаким другим потоком. Это не может произойти в Python. Поток может прервать другой поток между выполнением инструкций для создания сравнения и переключения, и тогда вам придется использовать поток вместо этого.
Простая блокировка необходима, когда вы хотите гарантировать, что последовательность инструкций байт-кода / или вызовов функций Python выполняется без того, чтобы другой поток их прерывал.
Давайте посмотрим на некоторый исходный код и соответствующие инструкции байт-кода:
a = 0
b = 0
def func():
global a
global b
# The const value 100 is loaded and stored in 'a'
a = 100
# 0 LOAD_CONST 1 (100)
# 3 STORE_GLOBAL 0 (a)
# The const value 200 is loaded and stored in 'b'
b = 200
# 6 LOAD_CONST 1 (200)
# 9 STORE_GLOBAL 0 (b)
Функция перезаписывает глобальные переменные a
а также b
со значениями 100 и 200. Если бы мы выполнили func
из двух потоков, мы можем быть уверены, что значения a
а также b
всегда будет действительным, потому что потоки могут просто переключаться между инструкциями байт-кода. Если бы мы написали эту функцию в C, то a
а также b
были бы атомные целые числа.
Для меня это выглядит коллекциями. Deque - это тот класс, который вы ищете. Это потокобезопасный стек, который гарантирует, что append или pop выполняются без прерывания. Deques также поддерживает эффективное добавление памяти и всплывающие окна.