asyncio-sync.md
1> **Источник:** https://python-all.ru/3.5/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.5/library/asyncio-sync.html#asyncio.Lock)12- [`Event`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Event)13- [`Condition`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Condition)1415Семафоры:1617- [`Semaphore`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Semaphore)18- [`BoundedSemaphore`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.BoundedSemaphore)1920API блокировок asyncio было разработано так, чтобы быть близким к классам модуля [`threading`](https://python-all.ru/3.5/library/threading.html#module-threading) ([`Lock`](https://python-all.ru/3.5/library/threading.html#threading.Lock), [`Event`](https://python-all.ru/3.5/library/threading.html#threading.Event), [`Condition`](https://python-all.ru/3.5/library/threading.html#threading.Condition), [`Semaphore`](https://python-all.ru/3.5/library/threading.html#threading.Semaphore), [`BoundedSemaphore`](https://python-all.ru/3.5/library/threading.html#threading.BoundedSemaphore)), но у него нет параметра *тайм-аут*. Функция [`asyncio.wait_for()`](https://python-all.ru/3.5/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.5/library/asyncio-sync.html#asyncio.Lock.acquire) и [`release()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Lock.release). Когда состояние разблокировано, acquire() изменяет состояние на заблокированное и возвращается немедленно. Когда состояние заблокировано, acquire() блокируется до тех пор, пока вызов release() в другой корутине не изменит его на разблокированное, затем вызов acquire() сбрасывает его в заблокированное и возвращается. Метод release() следует вызывать только в заблокированном состоянии; он изменяет состояние на разблокированное и возвращается немедленно. При попытке освободить разблокированную блокировку будет возбуждено исключение [`RuntimeError`](https://python-all.ru/3.5/library/exceptions.html#RuntimeError).3334Когда несколько корутин заблокированы в acquire() в ожидании перехода состояния в разблокированное, только одна корутина продолжает работу, когда вызов release() сбрасывает состояние в разблокированное; обрабатывается первая корутина, заблокированная в acquire().3536[`acquire()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Lock.acquire) является корутиной и должна вызываться с `yield from`.3738Блокировки также поддерживают протокол менеджера контекста. `(yield from lock)` следует использовать в качестве выражения менеджера контекста.3940This class is [не является потокобезопасным](https://python-all.ru/3.5/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.5/library/asyncio-task.html#coroutine).8485#### `release()`8687Освободить блокировку.8889Когда блокировка заблокирована, сбросить её в разблокированное состояние и вернуться. Если какие-либо другие корутины заблокированы в ожидании разблокировки блокировки, позволить ровно одной из них продолжить.9091При вызове на не заблокированной блокировке возбуждается исключение [`RuntimeError`](https://python-all.ru/3.5/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.5/library/threading.html#threading.Event).100101Класс, реализующий объекты событий. Событие управляет флагом, который может быть установлен в true с помощью метода [`set()`](https://python-all.ru/3.5/library/stdtypes.html#set) и сброшен в false с помощью метода [`clear()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Event.clear). Метод [`wait()`](https://python-all.ru/3.5/library/asyncio-task.html#asyncio.wait) блокируется до тех пор, пока флаг не станет true. Изначально флаг установлен в false.102103This class is [не является потокобезопасным](https://python-all.ru/3.5/library/asyncio-dev.html#asyncio-multithreading).104105#### `clear()`106107Сбросить внутренний флаг в false. После этого корутины, вызывающие [`wait()`](https://python-all.ru/3.5/library/asyncio-task.html#asyncio.wait), будут блокироваться до тех пор, пока не будет вызван [`set()`](https://python-all.ru/3.5/library/stdtypes.html#set) для повторной установки внутреннего флага в true.108109#### `is_set()`110111Возвращает `True` тогда и только тогда, когда внутренний флаг равен true.112113#### `set()`114115Установить внутренний флаг в true. Все корутины, ожидающие его перехода в true, пробуждаются. Корутины, вызывающие [`wait()`](https://python-all.ru/3.5/library/asyncio-task.html#asyncio.wait) после того, как флаг станет true, не будут блокироваться вообще.116117#### `coroutine wait()`118119Блокироваться до тех пор, пока внутренний флаг не станет true.120121Если внутренний флаг уже true при входе, немедленно вернуть `True`. В противном случае блокироваться до тех пор, пока другая корутина не вызовет [`set()`](https://python-all.ru/3.5/library/stdtypes.html#set), чтобы установить флаг в true, затем вернуть `True`.122123Этот метод является [корутиной](https://python-all.ru/3.5/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.5/library/threading.html#threading.Condition).130131Этот класс реализует объекты переменных условия. Переменная условия позволяет одной или нескольким корутинам ожидать, пока они не будут уведомлены другой корутиной.132133Если аргумент *блокировка* задан и не равен `None`, он должен быть объектом [`Lock`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Lock), и используется в качестве нижележащей блокировки. В противном случае создаётся новый объект [`Lock`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Lock), который используется в качестве нижележащей блокировки.134135This class is [не является потокобезопасным](https://python-all.ru/3.5/library/asyncio-dev.html#asyncio-multithreading).136137#### `coroutine acquire()`138139Захватывает базовую блокировку.140141Этот метод блокирует выполнение до тех пор, пока блокировка не будет разблокирована, затем устанавливает её в заблокированное состояние и возвращает `True`.142143Этот метод является [корутиной](https://python-all.ru/3.5/library/asyncio-task.html#coroutine).144145#### `notify(n=1)`146147По умолчанию пробуждает одну корутину, ожидающую на этом условии, если такая есть. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.5/library/exceptions.html#RuntimeError).148149Этот метод пробуждает не более *n* корутин, ожидающих переменную условия; он ничего не делает, если никакие корутины не ожидают.150151> **Примечание**152>153> Пробуждённая корутина на самом деле не возвращается из своего вызова [`wait()`](https://python-all.ru/3.5/library/asyncio-task.html#asyncio.wait) до тех пор, пока не сможет повторно захватить блокировку. Поскольку [`notify()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Condition.notify) не освобождает блокировку, это должен сделать её вызывающая сторона.154155#### `locked()`156157Возвращает `True`, если базовая блокировка захвачена.158159#### `notify_all()`160161Пробуждает все корутины, ожидающие на этом условии. Этот метод действует как [`notify()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Condition.notify), но пробуждает все ожидающие корутины вместо одной. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.5/library/exceptions.html#RuntimeError).162163#### `release()`164165Освобождает базовую блокировку.166167Когда блокировка заблокирована, сбросить её в разблокированное состояние и вернуться. Если какие-либо другие корутины заблокированы в ожидании разблокировки блокировки, разрешить ровно одной из них продолжить выполнение.168169При вызове на не заблокированной блокировке возбуждается исключение [`RuntimeError`](https://python-all.ru/3.5/library/exceptions.html#RuntimeError).170171Возвращаемое значение отсутствует.172173#### `coroutine wait()`174175Ожидает уведомления.176177Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.5/library/exceptions.html#RuntimeError).178179Этот метод освобождает нижележащую блокировку, а затем блокирует выполнение до тех пор, пока он не будет пробуждён вызовом [`notify()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Condition.notify) или [`notify_all()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Condition.notify_all) для той же переменной условия в другой корутине. После пробуждения он повторно захватывает блокировку и возвращает `True`.180181Этот метод является [корутиной](https://python-all.ru/3.5/library/asyncio-task.html#coroutine).182183#### `coroutine wait_for(predicate)`184185Ожидает, пока предикат не станет истинным.186187Предикат должен быть вызываемым объектом, результат которого будет интерпретироваться как логическое значение. Итоговое значение предиката является возвращаемым значением.188189Этот метод является [корутиной](https://python-all.ru/3.5/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.5/library/asyncio-sync.html#asyncio.Semaphore.acquire) и увеличивается при каждом вызове [`release()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Semaphore.release). Счётчик никогда не может опуститься ниже нуля; когда [`acquire()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Semaphore.acquire) обнаруживает, что он равен нулю, он блокирует выполнение, ожидая, пока какая-либо другая корутина вызовет [`release()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Semaphore.release).200201Семафоры также поддерживают протокол управления контекстом.202203Необязательный аргумент задаёт начальное значение внутреннего счётчика; по умолчанию он равен `1`. Если указанное значение меньше `0`, возбуждается [`ValueError`](https://python-all.ru/3.5/library/exceptions.html#ValueError).204205This class is [не является потокобезопасным](https://python-all.ru/3.5/library/asyncio-dev.html#asyncio-multithreading).206207#### `coroutine acquire()`208209Захватывает семафор.210211Если внутренний счётчик больше нуля на входе, уменьшить его на единицу и немедленно вернуть `True`. Если он равен нулю на входе, заблокировать выполнение, ожидая, пока какая-либо другая корутина вызовет [`release()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Semaphore.release), чтобы сделать его больше чем `0`, а затем вернуть `True`.212213Этот метод является [корутиной](https://python-all.ru/3.5/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.5/library/asyncio-sync.html#asyncio.Semaphore).228229Это возбуждает [`ValueError`](https://python-all.ru/3.5/library/exceptions.html#ValueError) в [`release()`](https://python-all.ru/3.5/library/asyncio-sync.html#asyncio.Semaphore.release), если при этом значение превысило бы начальное значение.230