2015-09-07 4 views

ответ

3

Вы упомянули CAS и атомные операции в конкретном, но стандартная реализация Python (CPython) работает с байтовым кодом и использует также так называемый глобальный блокиратор интерпретатора. Итак, вот некоторые соображения, почему есть no атомных операций в 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 были бы атомными целыми числами.

Для меня это collections.deque это класс, который вы ищете. Это потокобезопасный стек, который гарантирует, что append или pop выполняется без прерывания. Deques также поддерживает эффективные приложения и всплывающие подсказки.

+0

Спасибо @HelloWorld. Это здорово, но делает ** deque ** поддерживает CAS (сравнить и переключать) атомную работу? Это необходимо для обеспечения незакрепленной реализации стека. –

+0

Прочтите мой ответ еще раз. Python не работает так. В этом нет необходимости, и нет атомных операций. Вам нужно атомизировать, когда ваша среда поддерживает реальную многопоточность, это не так в CPython. Когда Python выполняет инструкцию байт-кода, он говорит «записывать x в y», тогда ** no ** другой поток может прерывать или делать что-либо еще в то же время. Вы можете быть уверены, что инструкция полностью выполняется, когда поток возвращается из выполнения этой инструкции.Когда вам нужна функция, которая делает сравнение и переключатель, вы должны использовать блокировку, - но опять же, это не атомный. – HelloWorld

Смежные вопросы