Почему Глобальная Блокировка Интерпретатора? - PullRequest
85 голосов
/ 05 ноября 2008

Какова функция глобальной блокировки интерпретатора Python? Используют ли другие языки, скомпилированные для байт-кода, аналогичный механизм?

Ответы [ 6 ]

68 голосов
/ 05 ноября 2008

В общем, для любой проблемы безопасности потоков вам нужно будет защитить внутренние структуры данных с помощью блокировок. Это может быть сделано с различными уровнями детализации.

  • Вы можете использовать мелкозернистую блокировку, когда каждая отдельная структура имеет свою собственную блокировку.

  • Вы можете использовать грубую блокировку, когда одна блокировка защищает все (подход GIL).

Существуют различные плюсы и минусы каждого метода. Мелкозернистая блокировка обеспечивает большую параллельность - два потока могут выполняется параллельно, когда они не разделяют какие-либо ресурсы. Однако административные издержки значительно выше. За каждая строка кода может потребоваться получить и снять несколько блокировок.

Крупнозернистый подход противоположен. Два потока не могут работать одновременно, но отдельный поток будет работать быстрее, потому что он не делает так много бухгалтерии. В конечном итоге все сводится к компромиссу между однопоточной скоростью и параллелизмом.

Было несколько попыток удалить GIL в python, но дополнительные издержки для однопоточных машин, как правило, были слишком большими. Некоторые случаи на самом деле могут быть медленнее даже на многопроцессорных компьютерах из-за блокировки блокировки.

Используют ли другие языки, скомпилированные для байт-кода, аналогичный механизм?

Это варьируется, и, вероятно, его не следует рассматривать как свойство языка, а как свойство реализации. Например, есть реализации Python, такие как Jython и IronPython, которые используют многопоточный подход своей базовой виртуальной машины, а не подход GIL. Кроме того, следующая версия Ruby, похоже, движется к , вводя GIL.

33 голосов
/ 05 ноября 2008

Ниже приведено официальное справочное руководство по API Python / C :

Интерпретатор Python не полностью Поток безопасно. Для того, чтобы поддержать многопоточные программы на Python, есть глобальная блокировка, которая должна быть удерживается текущим потоком перед ним может безопасно получить доступ к объектам Python. Без блокировки даже самый простой операции могут вызвать проблемы в многопоточная программа: например, когда два потока одновременно увеличить счетчик ссылок тот же объект, счетчик ссылок может в конечном итоге увеличивается только один раз вместо двух раз.

Следовательно, существует правило, что только нить, которая приобрела Глобальная блокировка интерпретатора может работать на Объекты Python или вызов API Python / C функции. Для того, чтобы поддержать многопоточные программы Python, переводчик регулярно выпускает и повторно захватывает блокировку - по умолчанию, каждые 100 байткодов инструкции (это можно изменить с помощью sys.setcheckinterval ()). Замок есть также выпущен и повторно приобретен вокруг потенциально блокирует операции ввода / вывода как чтение или запись файла, так что другие потоки могут работать в то время как поток, который запрашивает ввод / вывод ожидание операции ввода / вывода в полный.

Я думаю, что это довольно хорошо подводит итог.

19 голосов
/ 05 ноября 2008

Глобальная блокировка интерпретатора - это большая блокировка типа мьютекса, которая защищает счетчики ссылок от попадания. Если вы пишете чистый код Python, все это происходит за кулисами, но если вы встраиваете Python в C, вам, возможно, придется явно снять / снять блокировку.

Этот механизм не связан с тем, что Python компилируется в байт-код. Это не нужно для Java. На самом деле, это даже не нужно для Jython (python скомпилирован в jvm).

см. Также этот вопрос

11 голосов
/ 05 ноября 2008

Python, как и Perl 5, не был спроектирован с точки зрения безопасности потоков. После этого были созданы потоки, поэтому глобальная блокировка интерпретатора используется для поддержания взаимного исключения, когда только один поток выполняет код в определенный момент времени в недрах интерпретатора.

Отдельные потоки Python совместно выполняют многозадачность самим интерпретатором, периодически повторяя блокировку.

Требуется самостоятельно захватить блокировку, когда вы разговариваете с Python из C, когда другие потоки Python активны, чтобы включить этот протокол и убедиться, что за вашей спиной ничего опасного не происходит.

Другие системы, имеющие однопоточное наследие, которое впоследствии превратилось в многопоточные системы, часто имеют такой механизм. Например, ядро ​​Linux имеет «Big Kernel Lock» с первых дней SMP. Постепенно со временем, когда производительность многопоточности становится проблемой, возникает тенденция разбивать эти виды блокировок на более мелкие части или заменять их алгоритмами без блокировки и структурами данных, где это возможно, чтобы максимизировать пропускную способность.

7 голосов
/ 05 ноября 2008

Относительно вашего второго вопроса, не все языки сценариев используют это, но это только делает их менее мощными. Например, потоки в Ruby зеленые , а не нативные.

В Python потоки являются нативными, и GIL не позволяет им работать на разных ядрах.

В Perl потоки еще хуже. Они просто копируют весь интерпретатор и далеко не так удобны, как в Python.

2 голосов
/ 05 ноября 2008

Может быть эта статья BDFL поможет.

...