Найти в Дзене

Обеспечена потокобезопасность семафора в Python

🚦 Структура семафора SemLockObject, в реализации модуля multiprocessing, поддерживает внутреннее поле счетчика count. При работе в качестве рекурсивного мьютекса (RECURSIVE_MUTEX) count — это количество раз, когда поток захватывал мьютекс (т. е. 0, 1, .. N). А при работе в качестве семафора (SEMAPHORE) счетчик часто равен 0 или 1, но может быть отрицательным, если SemLockObject инициализируется с maxvalue > 1.

🔄 Изменение
count не является потокобезопасным без GIL внутри процесса. Обратите внимание, что поле count не является общим для всех процессов, в отличие от базового поля sem_t или HANDLE.

☠️ В частности, в этом
коде изменение count, после освобождения семафора, не является потокобезопасным без GIL:

-2

⛔️ Это может быть источником взаимоблокировок при работе с отключенным GIL.

💁‍♂️ Кажется немного странным вставлять блокировку в реализацию блокировки, но на удивление сложно сделать так, чтобы изменения считались потокобезопасными, особенно в случае использования
kind == SEMAPHORE, когда несколько потоков могут "освободить" семафор одновременно.

👌 Для
решения этой проблемы использованы CRITICAL_SECTION, чтобы обеспечить потокобезопасность методов Acquire(), Release() и _count() модуля без GIL.

👉 Подробнее в телеграм канале https://t.me/cpython_ru

#PEP703