У меня есть часть кода, где у меня есть поток обработки и поток монитора. В потоке обработки у меня есть вызов функции collections.deque.popleft. Я хотел бы знать, если эта функция освобождает GIL, потому что я хочу запустить мой монитор нитку, даже если функция обработки блокируется на функции popleftБудет ли метод collection.deque «pop» выпускать GIL?
ответ
Да - deque
потокобезопасно (спасибо @hemanths) http://docs.python.org/2/library/collections.html#collections.deque
Нет, потому что
collections.deque
не является потокобезопасным. Используйте
Queue или создайте собственный подкласс
deque
.
Интересно, верно ли это, согласно документации python' collections.deque' на самом деле является нитью безопасный для операций добавления и поп: [https://docs.python.org/2/library/collections.html#collections.deque] – hemanths
oops, @hemanths, вы правы - спасибо! – johntellsall
Вместо того, чтобы ответить на этот конкретный вопрос я ответить на другой вопрос:
Что такое Global Interpreter Lock (GIL), и когда он будет блокировать мою программу?
Короче говоря, GIL защищает состояние интерпретатора от повреждения из-за одновременных потоков.
Для определения того, что это такое для, рассмотрите реализацию низкого уровня dict
, в которой где-то есть массив ключей, организованный для быстрого поиска. Когда вы пишете код, как:
myDict['foo'] = 'bar'
питон интерпретатор должен настроить свою коллекцию ключей. Это может включать в себя такие вещи, как создание дополнительных возможностей для дополнительного ключа, а также добавление конкретного ключа к этому массиву.
Если несколько, одновременные потоки изменяют этот dict, то один поток может перераспределить массив, а другой находится в середине его изменения, что может вызвать некоторое непредсказуемое, вероятно, плохое поведение (что-либо из поврежденных данных, segfault или heartbleed like утечка содержимого содержимого конфиденциальных данных или выполнение произвольного кода)
Поскольку это не такое состояние, которое вы можете разумно описать или предотвратить на уровне вашего приложения python, время выполнения идет на большие длины, чтобы предотвратить подобные проблемы от происходящего. То, как он это делает, состоит в том, что некоторые части интерпретатора, такие как модификация dict, окружены парой /PyGILState_Release()
, так что критические операции всегда достигают согласованного состояния.
Обратите внимание, что scope этого замка очень узкий; он не пытается защитить от общих расов данных, он не защитит вас от написания программы с несколькими потоками, перезаписывающих работу друг друга в общем контейнере (скажем, collections.deque
), только если даже вы пишете такую программу , это не приведет к тому, что интерпретатор будет аварийно завершен, у вас всегда будет действующий deque
. Вы можете добавить дополнительные блокировки приложений, как в queue.Queue
, чтобы дать хорошую параллельную семантику вашему приложению.
Поскольку каждая операция, которую GIL защищает, является изменением состояния интерпретатора, она никогда не блокирует внешние события; поскольку эти события не будут изменять состояние интерпретатора, переменная условия сигнализации не может испортить память.
Единственный раз, когда у вас может быть проблема, когда у вас есть несколько разблокировал нити, так как они потенциально все исполняемого кода в интерпретаторе низкого уровня, они будут конкурировать за GIL, и только один поток может удерживать его, блокируя другие потоки, которые также хотят сделать некоторые вычисления.
Если вы не пишете C-расширения, вам, вероятно, не нужно беспокоиться об этом, и если у вас нет , то вы должны будете вычислить связанные потоки, в python, и на это не повлияет.
Спасибо, это было очень полезно – hemanths
Вы имеете в виду 'queue.Queue'? 'collections.deque' не имеет метода' get', и если бы он существовал, он не блокировался бы, потому что 'deque' не для параллелизма. – delnan
... и предполагая, что вы имеете в виду «очередь», ответ будет: конечно, он выпускает GIL. В противном случае это было бы бесполезно. – shx2
Я написал функцию get для моего пользовательского класса, полученного из 'collections.deque', я просто вызываю функцию popleft в этой функции – hemanths