Эта тема относится к области низкоуровневого программирования, и во многих случаях можно и без этих знаний успешно организовать многопоточную работу в программах на языке Python, но тем не менее реализация механизма потоков в Python может оказывать влияние как на производительность, так и на стиль программирования. В этом разделе приводятся сведения об особенностях реализации и о некоторых их следствиях.
# 4Я
О реализации потоков выполнения в грядущей версии Py Python 3.2: В этом разделе описывается текущая реализация
*’Ч’ 4 «я потоков выполнения, включая версию Python 3.1. К моменту ■ написания этих строк версия Python 3.2 все еще находилась в стадии разработки, но одним из нововведений в ней наверняка будет новая версия GIL, обеспечивающая более высокую производительность, особенно в системах с многоядерными процессорами. Новая реализация GIL по-прежнему будет синхронизировать доступ к PVM (программный код на языке Python по-прежнему будет мультиплексироваться, как и ранее), но она будет использовать более эффективную схему переключения контекста, чем ныне используемая схема переключения через N-инструкций-в-байткоде.
Помимо всего прочего, текущая функция sys.setcheckinterval, вероятно, будет заменена таймером с поддержкой новой схемы. В частности, понятие интервала проверки необходимости переключения потоков выполнения будет ликвидировано и заменено абсолютным значением продолжительности, выраженным в секундах. Как ожидается, это значение по умолчанию будет равно 5 миллисекундам, но его можно будет изменять с помощью функции sys.setswitchinterval.
Кроме того, существовало множество планов по полной ликвидации GIL (включая проект Unladen Swallow, запущенный сотрудниками Google), однако до сих пор не было представлено ни одного варианта решения. Я не берусь предсказывать будущее, поэтому читайте документацию к новым версиям Python, чтобы оставаться в курсе.
Строго говоря, в настоящее время Python использует механизм глобальной блокировки интерпретатора (Global Interpreter Lock, GIL), представленный в начале этого раздела и обеспечивающий выполнение интерпретатором Python в каждый конкретный момент времени программного кода не более чем одного потока. Кроме того, чтобы дать каждому потоку возможность поработать, интерпретатор автоматически переключается между ними через равные промежутки времени (в Python 3.1 — путем освобождения и приобретения блокировки после выполнения некоторого числа инструкций в байт-коде), а также в начале длительных операций (например, в начале операций ввода/вывода в файлы).
Такая схема позволяет избежать проблем, могущих возникнуть, когда нескольким потокам выполнения одновременно может потребоваться обновить системные данные Python. Например, если двум потокам разрешить одновременно изменить счетчик ссылок на объект, результаты могут оказаться непредсказуемыми. Применение этой схемы может также повлечь тонкие неочевидные последствия. В частности, в примерах использования потоков, приведенных в данной главе, мы видели, что при выводе в stdout текст может повреждаться, если потоки не синхронизируют свои операции вывода с помощью блокировок.
Кроме того, хотя глобальная блокировка интерпретатора не разрешает одновременно выполнять более одного потока Python, этого недостаточно для обеспечения безопасности потоков в целом и это никак не решает проблемы синхронизации на более высоком уровне. Например, если одновременно несколько потоков пытаются изменить одну и ту же переменную, им обычно должен предоставляться исключительный доступ к объекту с помощью блокировок. В противном случае существует вероятность, что переключение потоков произойдет посреди байт-кода выражения, осуществляющего изменение.
Не обязательно использовать блокировки для обращения ко всем совместно используемым объектам, особенно если только один поток изменяет объект, а остальные только наблюдают за изменениями. Возьмите за правило всегда использовать блокировки для синхронизации потоков в тех случаях, когда возможна конкуренция в операции изменения, не полагаясь на текущий способ реализации потоков.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011