@v1ceo

Почему без GIL в Python подсчёт ссылок НЕ является безопасным?

Изучаю информацию по GIL и как я понял без него потоки работали бы параллельно и счётчик ссылок работал бы некорректно (race conditions), что приводило бы к ошибкам.
Если точнее
А вот когда программа запускается в многопоточном режиме и если не используется GIL , то возникают проблемы с преждевременным удалением объектов и другими проблемами связанными с управлением памяти. Это происходит из-за того, что несколько потоков одновременно могут увеличивать или уменьшать значения счётчика ссылок на объект.


Также нашёл подобный вопрос на Хабре , но на мой взгляд ответ там не совсем корректен, ТАК КАК
Вариант 1 и Вариант 2 могут происходить даже при последовательных потоков, так как операция присваивания значения переменной X состоит из трёх операций: ЧТЕНИЕ её значения, ИЗМЕНЕНИЕ её значения, ВОЗВРАТ значения.
Так вот, при последовательных процессах первый поток может прочитать значение переменной(оно равно = 1) и затем передать управление второму потоку, который также прочитает это значение(оно также всё ещё равно = 1), потом управление передаётся первому потому, который прибавляет единицу и возвращает значение в память (то есть вернёт первый поток 2), далее управление идёт ко второму потоку и там он также прибавляет единицу (к значению 1, так как именно это значение он прочитал до этого) и возвращает в память также значение 2 (хотя по факту мы прибавляли единицу два раза и по итогу должно было быть значение 3); Поэтому для ТАКИХ СЛУЧАЕВ существует такая штука как LOCK

Но вот как именно помогает GIL подсчёту ссылок я так и не понял. Или ,например, если есть два потока, работающих с одной глобальной переменной, то первый поток использует значение этой переменной и прямо СРАЗУ ЖЕ при использовании добавляет в счётчик ссылок +1,
и не может быть такого, что он использует значение объекта из памяти, не сделает +1 к счётчику ссылок(так как не успеет сделать этого из за передачи управления второму потоку), но запомнит, что счётчик ссылок был равен условно говоря 2, потом этот же объект использует второй поток и добавит к счётчику ссылок +1, но так как первый поток не изменил значения в память вернётся значения счётчика ссылок для этого объекта равное 3, при обратной передачи управления первому потоку он наконец прибавит +1 к счетчику ссылок, но так как он считывал счётчик ссылок равный 2, то прибавит 1 именно к 2, и вернёт ту же 3 в счётчик ссылок, хотя должно быть уже 4.
  • Вопрос задан
  • 138 просмотров
Решения вопроса 1
Насчет механизма подсчета ссылок и GIL подробно не расскажу, насколько я помню, он предотвращает ситуацию, когда два потока одновременно изменяют счетчик ссылок, что может привести к некорректным результатам.

Также GIL используется для правильной работы структур list, dict, set. На примере работы list: https://habr.com/ru/post/273045/. Вставка элемента в позицию x требует смещения некоторых элементов списка, например, если мы хотим вставить элемент в середину списка, то перед вставкой интерпретатору нужно будет сдвинуть второю половину листа. Теперь представим ситуацию, есть список в котором 10 элементов, один поток хочет вставить элемент во второй индекс, а второй поток - в третий индекс. В этом случае потоки могут помешать друг другу и элементы сместятся не правильно.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы