Источник -
- Дэвид Бизли — https://www.youtube.com/watch?v=Obt-vMVdM8s
- Ларри Гастингс — https://www.youtube.com/watch?v=KVKufdTphKs
- Джеймс Пауэлл (Последний раздел Asyncio) в Advanced Python on Safari Video.
GIL расшифровывается как Global Interpreter Lock. Он блокирует использование ЦП для одного потока за раз. Он используется Cpython и PyPy (но не Jython и IronPython). Чтобы понять это, давайте попробуем понять необходимость GIL.
Зачем нужен ГИЛ?
- Атомарность. Если несколько потоков пытались изменить атрибут модуля или любую глобальную переменную, может возникнуть состояние гонки.
- Подсчет ссылок. Если несколько потоков изменяют счетчик ссылок на один и тот же объект одновременно, то произойдет либо утечка памяти (объект не может быть удален), либо объект
- Предотвращение взаимоблокировок. Не может быть взаимоблокировок, которые случаются в многопоточных программах.
- Расширения C —
GIL также помогает пользователям определять расписание и решать, какие задачи запускать и в каком порядке (генераторы и сопрограммы помогают планировать). В многопоточности планирование является проблемой (подумайте о недостатках многопоточности)
Python использует настоящие системные потоки — Posix (pthreads) или Windows Threads.
По этим причинам был введен GIL. Разветвления —
- Простой и поэтому легко читаемый код.
- Тяжелый многопоточный код ввода-вывода работает довольно хорошо, поскольку переключение контекста происходит, когда происходит ввод-вывод, например, для сна, чтения + записи из сокета/файла.
- Многопоточный код, связанный с ЦП, работает медленно, поскольку ввод-вывод не происходит.
Как работает «совместная многозадачность»
Когда есть другой поток, желающий приобрести GIL —
- В Python v2 он ждал, пока работающий поток освободит GIL, выполнив ввод-вывод.
- В Python v3 это сигнализировало бы другому потоку о его освобождении. (код добавлен Антуаном Питру)
А как насчет многоядерных систем?
Как избежать GIL —
- Использовать процессы