Какова именно функция глобальной блокировки интерпретатора Python? Используют ли другие языки, компилируемые в байт-код, аналогичный механизм?
Я согласен, я считаю, что теперь это не проблема, потому что в 2.6 был добавлен модуль многопроцессорности, позволяющий программировать с использованием нескольких процессов потокоподобным образом. docs.python.org/library/multiprocessing.html
Что такое Гил: stackoverflow.com/questions/1294382/…, связанный с программистами: softwareengineering.stackexchange.com/questions/186889/…






Следующее взято из официальное справочное руководство по Python / C API:
The Python interpreter is not fully thread safe. In order to support multi-threaded Python programs, there's a global lock that must be held by the current thread before it can safely access Python objects. Without the lock, even the simplest operations could cause problems in a multi-threaded program: for example, when two threads simultaneously increment the reference count of the same object, the reference count could end up being incremented only once instead of twice.
Therefore, the rule exists that only the thread that has acquired the global interpreter lock may operate on Python objects or call Python/C API functions. In order to support multi-threaded Python programs, the interpreter regularly releases and reacquires the lock -- by default, every 100 bytecode instructions (this can be changed with sys.setcheckinterval()). The lock is also released and reacquired around potentially blocking I/O operations like reading or writing a file, so that other threads can run while the thread that requests the I/O is waiting for the I/O operation to complete.
Я думаю, что это довольно хорошо резюмирует проблему.
Я тоже читал, но не могу понять, чем Python в этом отношении отличается, скажем, от java (не так ли?)
Потоки @EliBendersky Python реализованы как потоки pthread и обрабатываются ОС (dabeaz.com/python/UnderstandingGIL.pdf), тогда как потоки Java - это потоки уровня приложения, планирование которых обрабатывается JVM.
Глобальная блокировка интерпретатора - это большая блокировка типа мьютекса, которая защищает счетчики ссылок от перехвата. Если вы пишете чистый код Python, все это происходит за кулисами, но если вы встраиваете Python в C, вам, возможно, придется явно снять / снять блокировку.
Этот механизм не связан с компиляцией Python в байт-код. Для Java это не нужно. Фактически, это даже не нужно для Jython (python скомпилирован в jvm).
см. также этот вопрос
«Этот механизм не связан с компиляцией Python в байт-код»: точнее, это артефакт реализации CPython. Другие реализации (например, Jython, о котором вы упомянули) могут быть свободны от этого ограничения в силу их поточно-ориентированной реализации.
Что касается вашего второго вопроса, не все языки сценариев используют это, но это только делает их менее мощными. Например, потоки в Ruby - это зеленый, а не собственные.
В Python потоки являются собственными, и GIL только предотвращает их запуск на разных ядрах.
В Perl потоки еще хуже. Они просто копируют интерпретатор целиком и далеко не так удобны, как в Python.
В общем, для решения любой проблемы безопасности потоков вам необходимо защитить свои внутренние структуры данных с помощью блокировок. Это можно сделать с различными уровнями детализации.
Вы можете использовать мелкозернистую блокировку, когда каждая отдельная структура имеет свою собственную блокировку.
Вы можете использовать грубую блокировку, когда одна блокировка защищает все (подход GIL).
У каждого метода есть свои плюсы и минусы. Мелкозернистая блокировка обеспечивает больший параллелизм - два потока могут выполняются параллельно, когда у них нет общих ресурсов. Однако существуют гораздо большие административные издержки. Для для каждой строчки кода может потребоваться получение и снятие нескольких блокировок.
При крупнозернистом подходе все наоборот. Два потока не могут выполняться одновременно, но отдельный поток будет работать быстрее, потому что он не выполняет так много учетных записей. В конечном итоге все сводится к компромиссу между однопоточной скоростью и параллелизмом.
Было предпринято несколько попыток удалить GIL в python, но дополнительные накладные расходы для однопоточных машин, как правило, были слишком большими. Некоторые случаи могут быть медленнее даже на многопроцессорных машинах. из-за конфликта блокировок.
Do other languages that are compiled to bytecode employ a similar mechanism?
Он варьируется, и, вероятно, его не следует рассматривать как свойство языка в большей степени, чем свойство реализации. Например, существуют реализации Python, такие как Jython и IronPython, которые используют поточный подход своей базовой виртуальной машины, а не подход GIL. Кроме того, следующая версия Ruby, похоже, будет перемещать к, вводя GIL.
можете ли вы объяснить это: «Два потока не могут работать одновременно»? Недавно я написал простой веб-сервер на Python с многопоточностью. Для каждого нового запроса от клиента серверы порождают для него новый поток, и этот поток продолжает выполняться. Значит, одновременно будет работать несколько потоков? Или я неправильно понял?
@avi AFAIK потоки python не могут работать одновременно, но это не значит, что один поток должен блокировать другой. GIL означает только то, что только один поток может интерпретировать код Python одновременно, это не означает, что управление потоками и распределение ресурсов не работают.
^ поэтому в любой момент времени только один поток будет обслуживать контент для клиента ... поэтому нет смысла использовать многопоточность для повышения производительности. Правильно?
И, конечно же, Java скомпилирована в байтовый код и допускает очень мелкозернистую блокировку.
@avi, процесс, связанный с вводом-выводом, такой как веб-сервер, все еще может получать выгоду от потоков Python. Два или более потока могут выполнять ввод-вывод одновременно. Они просто не могут быть интерпретированы (CPU) одновременно.
@avi и все, кто хочет узнать больше о GIL, dabeaz.com/python/UnderstandingGIL.pdf
Python, как и Perl 5, изначально не разрабатывался как потокобезопасный. Потоки были наложены постфактум, поэтому глобальная блокировка интерпретатора используется для поддержания взаимного исключения, когда только один поток выполняет код в данный момент времени в недрах интерпретатора.
Отдельные потоки Python совместно выполняют многозадачность самим интерпретатором, время от времени циклически переключая блокировку.
Самостоятельный захват блокировки необходим, когда вы разговариваете с Python из C, когда другие потоки Python активны, чтобы «подключиться» к этому протоколу и убедиться, что за вашей спиной ничего небезопасного не происходит.
Другие системы, унаследованные от однопоточных, которые позже превратились в многопоточные системы, часто имеют какой-либо механизм такого рода. Например, ядро Linux имеет «большую блокировку ядра» с первых дней SMP. Постепенно, по мере того, как производительность многопоточности становится проблемой, появляется тенденция пытаться разбить такого рода блокировки на более мелкие части или заменить их алгоритмами без блокировок и структурами данных, где это возможно, чтобы максимизировать пропускную способность.
+1 за упоминание того факта, что используется грубая блокировка, чем многие думают, особенно часто забываемый BKL (я использую reiserfs - единственная реальная причина, по которой я вообще знаю об этом).
В Linux был BKL, начиная с версии 2.6.39, BKL был полностью удален.
Конечно. Имейте в виду, что это было примерно через 3 года после того, как я ответил на вопрос. знак равно
Возможно, вам поможет статья это от BDFL.
Вы также должны спросить: "Это вообще имеет значение?"