asyncio-sync.md
1> **Источник:** https://python-all.ru/3.4/library/asyncio-sync.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 18.5.7. Примитивы синхронизации89Блокировки:1011- [`Lock`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Lock)12- [`Event`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Event)13- [`Condition`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Condition)1415Семафоры:1617- [`Semaphore`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Semaphore)18- [`BoundedSemaphore`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.BoundedSemaphore)1920API блокировок asyncio разработан так, чтобы быть близким к классам модуля [`threading`](https://python-all.ru/3.4/library/threading.html#module-threading) ([`Lock`](https://python-all.ru/3.4/library/threading.html#threading.Lock), [`Event`](https://python-all.ru/3.4/library/threading.html#threading.Event), [`Condition`](https://python-all.ru/3.4/library/threading.html#threading.Condition), [`Semaphore`](https://python-all.ru/3.4/library/threading.html#threading.Semaphore), [`BoundedSemaphore`](https://python-all.ru/3.4/library/threading.html#threading.BoundedSemaphore)), но не имеет параметра *timeout*. Функцию [`asyncio.wait_for()`](https://python-all.ru/3.4/library/asyncio-task.html#asyncio.wait_for) можно использовать для отмены задачи по таймауту.2122## 18.5.7.1. Блокировки2324### 18.5.7.1.1. Блокировка2526#### `class asyncio.Lock(*, loop=None)`2728Объекты примитивных блокировок.2930Примитивная блокировка – это примитив синхронизации, который не принадлежит конкретной корутине, когда заблокирован. Примитивная блокировка находится в одном из двух состояний: «locked» или «unlocked».3132Он создаётся в разблокированном состоянии. У него есть два основных метода: [`acquire()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Lock.acquire) и [`release()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Lock.release). Когда блокировка разблокирована, acquire() переводит её в заблокированное состояние и немедленно возвращается. Когда блокировка заблокирована, acquire() блокируется до тех пор, пока вызов release() в другой корутине не переведёт её в разблокированное состояние, после чего вызов acquire() снова устанавливает блокировку и возвращается. Метод release() должен вызываться только в заблокированном состоянии; он переводит блокировку в разблокированное состояние и немедленно завершается. При попытке освободить разблокированную блокировку будет возбуждено исключение [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError).3334Когда несколько корутин заблокированы в acquire() в ожидании перехода состояния в разблокированное, только одна корутина продолжает работу, когда вызов release() сбрасывает состояние в разблокированное; обрабатывается первая корутина, заблокированная в acquire().3536[`acquire()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Lock.acquire) является корутиной и должна вызываться через `yield from`.3738Блокировки также поддерживают протокол менеджера контекста. Выражение `(yield from lock)` должно использоваться в качестве выражения менеджера контекста.3940This class is [*не является потокобезопасным*](https://python-all.ru/3.4/library/asyncio-dev.html#asyncio-multithreading).4142Использование:4344```python45lock = Lock()46...47yield from lock48try:49 ...50finally:51 lock.release()52```5354Использование менеджера контекста:5556```python57lock = Lock()58...59with (yield from lock):60 ...61```6263Объекты блокировки можно проверить на состояние блокировки:6465```python66if not lock.locked():67 yield from lock68else:69 # блокировка получена70 ...71```7273#### `locked()`7475Возвращает `True`, если блокировка захвачена.7677#### `coroutine acquire()`7879Захватить блокировку.8081Этот метод блокируется до тех пор, пока блокировка не будет разблокирована, затем устанавливает её в заблокированное состояние и возвращает `True`.8283Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).8485#### `release()`8687Освободить блокировку.8889Когда блокировка заблокирована, сбросить её в разблокированное состояние и вернуться. Если какие-либо другие корутины заблокированы в ожидании разблокировки блокировки, позволить ровно одной из них продолжить.9091При вызове на разблокированной блокировке возбуждается [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError).9293Возвращаемое значение отсутствует.9495### 18.5.7.1.2. Event9697#### `class asyncio.Event(*, loop=None)`9899Реализация Event, асинхронный аналог [`threading.Event`](https://python-all.ru/3.4/library/threading.html#threading.Event).100101Класс, реализующий объекты событий. Событие управляет флагом, который можно установить в true с помощью метода [`set()`](https://python-all.ru/3.4/library/stdtypes.html#set) и сбросить в false с помощью метода [`clear()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Event.clear). Метод [`wait()`](https://python-all.ru/3.4/library/asyncio-task.html#asyncio.wait) блокируется, пока флаг не станет true. Изначально флаг равен false.102103This class is [*не является потокобезопасным*](https://python-all.ru/3.4/library/asyncio-dev.html#asyncio-multithreading).104105#### `clear()`106107Сбрасывает внутренний флаг в false. После этого корутины, вызывающие [`wait()`](https://python-all.ru/3.4/library/asyncio-task.html#asyncio.wait), будут блокироваться, пока не будет вызван [`set()`](https://python-all.ru/3.4/library/stdtypes.html#set), чтобы снова установить внутренний флаг в true.108109#### `is_set()`110111Возвращает `True` тогда и только тогда, когда внутренний флаг равен true.112113#### `set()`114115Устанавливает внутренний флаг в true. Все корутины, ожидающие его установки в true, пробуждаются. Корутины, вызывающие [`wait()`](https://python-all.ru/3.4/library/asyncio-task.html#asyncio.wait) после того, как флаг уже true, не будут блокироваться вовсе.116117#### `coroutine wait()`118119Блокироваться до тех пор, пока внутренний флаг не станет true.120121Если при входе внутренний флаг равен true, немедленно возвращает `True`. В противном случае блокируется до тех пор, пока другая корутина не вызовет [`set()`](https://python-all.ru/3.4/library/stdtypes.html#set) для установки флага в true, после чего возвращает `True`.122123Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).124125### 18.5.7.1.3. Condition126127#### `class asyncio.Condition(lock=None, *, loop=None)`128129Реализация Condition, асинхронный аналог [`threading.Condition`](https://python-all.ru/3.4/library/threading.html#threading.Condition).130131Этот класс реализует объекты переменных условия. Переменная условия позволяет одной или нескольким корутинам ожидать, пока они не будут уведомлены другой корутиной.132133Если передан аргумент *блокировка* и он не равен `None`, он должен быть объектом [`Блокировка`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Lock), который используется в качестве нижележащей блокировки. В противном случае создаётся новый объект [`Блокировка`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Lock) и используется как нижележащая блокировка.134135This class is [*не является потокобезопасным*](https://python-all.ru/3.4/library/asyncio-dev.html#asyncio-multithreading).136137#### `coroutine acquire()`138139Захватывает базовую блокировку.140141Этот метод блокируется, пока блокировка не будет освобождена, затем захватывает её и возвращает `True`.142143Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).144145#### `notify(n=1)`146147По умолчанию пробуждает одну корутину, ожидающую на этом условии (если такая есть). Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError).148149Этот метод пробуждает не более *n* корутин, ожидающих переменную условия; он ничего не делает, если никакие корутины не ожидают.150151> **Примечание**152>153> Пробуждённая корутина на самом деле не возвращается из вызова [`wait()`](https://python-all.ru/3.4/library/asyncio-task.html#asyncio.wait), пока не сможет повторно захватить блокировку. Поскольку [`notify()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Condition.notify) не освобождает блокировку, это должен сделать её вызывающий код.154155#### `locked()`156157Возвращает `True`, если нижележащая блокировка захвачена.158159#### `notify_all()`160161Пробуждает все корутины, ожидающие на этом условии. Этот метод действует как [`notify()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Condition.notify), но пробуждает все ожидающие корутины, а не одну. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError).162163#### `release()`164165Освобождает базовую блокировку.166167Когда блокировка заблокирована, сбросить её в разблокированное состояние и вернуться. Если какие-либо другие корутины заблокированы в ожидании разблокировки блокировки, разрешить ровно одной из них продолжить выполнение.168169При вызове на незахваченной блокировке возбуждается [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError).170171Возвращаемое значение отсутствует.172173#### `coroutine wait()`174175Ожидает уведомления.176177Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.4/library/exceptions.html#RuntimeError).178179Этот метод освобождает нижележащую блокировку, а затем блокируется, пока не будет пробуждён вызовом [`notify()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Condition.notify) или [`notify_all()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Condition.notify_all) на той же переменной условия в другой корутине. После пробуждения он повторно захватывает блокировку и возвращает `True`.180181Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).182183#### `coroutine wait_for(predicate)`184185Ожидает, пока предикат не станет истинным.186187Предикат должен быть вызываемым объектом, результат которого будет интерпретироваться как логическое значение. Итоговое значение предиката является возвращаемым значением.188189Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).190191## 18.5.7.2. Семафоры192193### 18.5.7.2.1. Semaphore194195#### `class asyncio.Semaphore(value=1, *, loop=None)`196197Реализация семафора.198199Семафор управляет внутренним счётчиком, который уменьшается при каждом вызове [`acquire()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Semaphore.acquire) и увеличивается при каждом вызове [`release()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Semaphore.release). Счётчик никогда не может стать отрицательным; когда [`acquire()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Semaphore.acquire) обнаруживает, что он равен нулю, он блокируется, ожидая, пока другая корутина вызовет [`release()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Semaphore.release).200201Семафоры также поддерживают протокол управления контекстом.202203Необязательный аргумент задаёт начальное значение внутреннего счётчика; по умолчанию оно равно `1`. Если переданное значение меньше `0`, возбуждается [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError).204205This class is [*не является потокобезопасным*](https://python-all.ru/3.4/library/asyncio-dev.html#asyncio-multithreading).206207#### `coroutine acquire()`208209Захватывает семафор.210211Если при входе внутренний счётчик больше нуля, уменьшить его на единицу и сразу вернуть `True`. Если он равен нулю при входе, заблокироваться, ожидая, пока другая корутина вызовет [`release()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Semaphore.release), чтобы сделать его больше `0`, а затем вернуть `True`.212213Этот метод является [*корутиной*](https://python-all.ru/3.4/library/asyncio-task.html#coroutine).214215#### `locked()`216217Возвращает `True`, если семафор не может быть захвачен немедленно.218219#### `release()`220221Освободить семафор, увеличивая внутренний счётчик на единицу. Если он был равен нулю на входе и другая корутина ожидает, пока он снова станет больше нуля, пробудить эту корутину.222223### 18.5.7.2.2. BoundedSemaphore224225#### `class asyncio.BoundedSemaphore(value=1, *, loop=None)`226227Реализация ограниченного семафора. Наследует от [`Semaphore`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Semaphore).228229Это возбуждает [`ValueError`](https://python-all.ru/3.4/library/exceptions.html#ValueError) в [`release()`](https://python-all.ru/3.4/library/asyncio-sync.html#asyncio.Semaphore.release), если это приведёт к увеличению значения выше начального.230