asyncio-sync.md
1> **Источник:** https://python-all.ru/3.6/library/asyncio-sync.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 18.5.7. Примитивы синхронизации89**Исходный код:** [Lib/asyncio/locks.py](https://python-all.ru/src/3.6/Lib/asyncio/locks.py)1011Блокировки:1213- [`Lock`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock)14- [`Event`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Event)15- [`Condition`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition)1617Семафоры:1819- [`Semaphore`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore)20- [`BoundedSemaphore`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.BoundedSemaphore)2122API блокировок asyncio было разработано так, чтобы быть близким к классам модуля [`threading`](https://python-all.ru/3.6/library/threading.html#module-threading) ([`Lock`](https://python-all.ru/3.6/library/threading.html#threading.Lock), [`Event`](https://python-all.ru/3.6/library/threading.html#threading.Event), [`Condition`](https://python-all.ru/3.6/library/threading.html#threading.Condition), [`Semaphore`](https://python-all.ru/3.6/library/threading.html#threading.Semaphore), [`BoundedSemaphore`](https://python-all.ru/3.6/library/threading.html#threading.BoundedSemaphore)), но у него нет параметра *тайм-аут*. Функция [`asyncio.wait_for()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait_for) может использоваться для отмены задачи по тайм-ауту.2324## 18.5.7.1. Блокировки2526### 18.5.7.1.1. Блокировка2728#### `class asyncio.Lock(*, loop=None)`2930Объекты примитивных блокировок.3132Примитивная блокировка – это примитив синхронизации, который не принадлежит конкретной корутине, когда заблокирован. Примитивная блокировка находится в одном из двух состояний: «locked» или «unlocked».3334Она создаётся в разблокированном состоянии. У неё есть два основных метода: [`acquire()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock.acquire) и [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock.release). Когда состояние разблокировано, acquire() изменяет состояние на заблокированное и возвращается немедленно. Когда состояние заблокировано, acquire() блокируется до тех пор, пока вызов release() в другой корутине не изменит его на разблокированное, затем вызов acquire() сбрасывает его в заблокированное и возвращается. Метод release() следует вызывать только в заблокированном состоянии; он изменяет состояние на разблокированное и возвращается немедленно. При попытке освободить разблокированную блокировку будет возбуждено исключение [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).3536Когда несколько корутин заблокированы в acquire() в ожидании перехода состояния в разблокированное, только одна корутина продолжает работу, когда вызов release() сбрасывает состояние в разблокированное; обрабатывается первая корутина, заблокированная в acquire().3738[`acquire()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock.acquire) является корутиной и должна вызываться с `yield from`.3940Блокировки также поддерживают протокол менеджера контекста. `(yield from lock)` следует использовать в качестве выражения менеджера контекста.4142This class is [не является потокобезопасным](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading).4344Использование:4546```python47lock = Lock()48...49yield from lock50try:51 ...52finally:53 lock.release()54```5556Использование менеджера контекста:5758```python59lock = Lock()60...61with (yield from lock):62 ...63```6465Объекты блокировки можно проверить на состояние блокировки:6667```python68if not lock.locked():69 yield from lock70else:71 # блокировка получена72 ...73```7475#### `locked()`7677Возвращает `True`, если блокировка захвачена.7879#### `coroutine acquire()`8081Захватить блокировку.8283Этот метод блокируется до тех пор, пока блокировка не будет разблокирована, затем устанавливает её в заблокированное состояние и возвращает `True`.8485Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).8687#### `release()`8889Освободить блокировку.9091Когда блокировка заблокирована, сбросить её в разблокированное состояние и вернуться. Если какие-либо другие корутины заблокированы в ожидании разблокировки блокировки, позволить ровно одной из них продолжить.9293При вызове на не заблокированной блокировке возбуждается исключение [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).9495Возвращаемое значение отсутствует.9697### 18.5.7.1.2. Event9899#### `class asyncio.Event(*, loop=None)`100101Реализация Event, асинхронный эквивалент [`threading.Event`](https://python-all.ru/3.6/library/threading.html#threading.Event).102103Класс, реализующий объекты событий. Событие управляет флагом, который может быть установлен в true с помощью метода [`set()`](https://python-all.ru/3.6/library/stdtypes.html#set) и сброшен в false с помощью метода [`clear()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Event.clear). Метод [`wait()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait) блокируется до тех пор, пока флаг не станет true. Изначально флаг установлен в false.104105This class is [не является потокобезопасным](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading).106107#### `clear()`108109Сбросить внутренний флаг в false. После этого корутины, вызывающие [`wait()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait), будут блокироваться до тех пор, пока не будет вызван [`set()`](https://python-all.ru/3.6/library/stdtypes.html#set) для повторной установки внутреннего флага в true.110111#### `is_set()`112113Возвращает `True` тогда и только тогда, когда внутренний флаг равен true.114115#### `set()`116117Установить внутренний флаг в true. Все корутины, ожидающие его перехода в true, пробуждаются. Корутины, вызывающие [`wait()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait) после того, как флаг станет true, не будут блокироваться вообще.118119#### `coroutine wait()`120121Блокироваться до тех пор, пока внутренний флаг не станет true.122123Если внутренний флаг уже true при входе, немедленно вернуть `True`. В противном случае блокироваться до тех пор, пока другая корутина не вызовет [`set()`](https://python-all.ru/3.6/library/stdtypes.html#set), чтобы установить флаг в true, затем вернуть `True`.124125Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).126127### 18.5.7.1.3. Condition128129#### `class asyncio.Condition(lock=None, *, loop=None)`130131Реализация Condition, асинхронный эквивалент [`threading.Condition`](https://python-all.ru/3.6/library/threading.html#threading.Condition).132133Этот класс реализует объекты переменных условия. Переменная условия позволяет одной или нескольким корутинам ожидать, пока они не будут уведомлены другой корутиной.134135Если аргумент *блокировка* задан и не равен `None`, он должен быть объектом [`Lock`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock), и используется в качестве нижележащей блокировки. В противном случае создаётся новый объект [`Lock`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Lock), который используется в качестве нижележащей блокировки.136137This class is [не является потокобезопасным](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading).138139#### `coroutine acquire()`140141Захватывает базовую блокировку.142143Этот метод блокирует выполнение до тех пор, пока блокировка не будет разблокирована, затем устанавливает её в заблокированное состояние и возвращает `True`.144145Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).146147#### `notify(n=1)`148149По умолчанию пробуждает одну корутину, ожидающую на этом условии, если такая есть. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).150151Этот метод пробуждает не более *n* корутин, ожидающих переменную условия; он ничего не делает, если никакие корутины не ожидают.152153> **Примечание**154>155> Пробуждённая корутина на самом деле не возвращается из своего вызова [`wait()`](https://python-all.ru/3.6/library/asyncio-task.html#asyncio.wait) до тех пор, пока не сможет повторно захватить блокировку. Поскольку [`notify()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition.notify) не освобождает блокировку, это должен сделать её вызывающая сторона.156157#### `locked()`158159Возвращает `True`, если базовая блокировка захвачена.160161#### `notify_all()`162163Пробуждает все корутины, ожидающие на этом условии. Этот метод действует как [`notify()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition.notify), но пробуждает все ожидающие корутины вместо одной. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).164165#### `release()`166167Освобождает базовую блокировку.168169Когда блокировка заблокирована, сбросить её в разблокированное состояние и вернуться. Если какие-либо другие корутины заблокированы в ожидании разблокировки блокировки, разрешить ровно одной из них продолжить выполнение.170171При вызове на не заблокированной блокировке возбуждается исключение [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).172173Возвращаемое значение отсутствует.174175#### `coroutine wait()`176177Ожидает уведомления.178179Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается [`RuntimeError`](https://python-all.ru/3.6/library/exceptions.html#RuntimeError).180181Этот метод освобождает нижележащую блокировку, а затем блокирует выполнение до тех пор, пока он не будет пробуждён вызовом [`notify()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition.notify) или [`notify_all()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Condition.notify_all) для той же переменной условия в другой корутине. После пробуждения он повторно захватывает блокировку и возвращает `True`.182183Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).184185#### `coroutine wait_for(predicate)`186187Ожидает, пока предикат не станет истинным.188189Предикат должен быть вызываемым объектом, результат которого будет интерпретироваться как логическое значение. Итоговое значение предиката является возвращаемым значением.190191Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).192193## 18.5.7.2. Семафоры194195### 18.5.7.2.1. Семафор196197#### `class asyncio.Semaphore(value=1, *, loop=None)`198199Реализация семафора.200201Семафор управляет внутренним счётчиком, который уменьшается при каждом вызове [`acquire()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.acquire) и увеличивается при каждом вызове [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.release). Счётчик никогда не может опуститься ниже нуля; когда [`acquire()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.acquire) обнаруживает, что он равен нулю, он блокирует выполнение, ожидая, пока какая-либо другая корутина вызовет [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.release).202203Семафоры также поддерживают протокол управления контекстом.204205Необязательный аргумент задаёт начальное значение внутреннего счётчика; по умолчанию он равен `1`. Если указанное значение меньше `0`, возбуждается [`ValueError`](https://python-all.ru/3.6/library/exceptions.html#ValueError).206207This class is [не является потокобезопасным](https://python-all.ru/3.6/library/asyncio-dev.html#asyncio-multithreading).208209#### `coroutine acquire()`210211Захватывает семафор.212213Если внутренний счётчик больше нуля на входе, уменьшить его на единицу и немедленно вернуть `True`. Если он равен нулю на входе, заблокировать выполнение, ожидая, пока какая-либо другая корутина вызовет [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.release), чтобы сделать его больше чем `0`, а затем вернуть `True`.214215Этот метод является [корутиной](https://python-all.ru/3.6/library/asyncio-task.html#coroutine).216217#### `locked()`218219Возвращает `True`, если семафор не может быть захвачен немедленно.220221#### `release()`222223Освободить семафор, увеличивая внутренний счётчик на единицу. Если он был равен нулю на входе и другая корутина ожидает, пока он снова станет больше нуля, пробудить эту корутину.224225### 18.5.7.2.2. BoundedSemaphore226227#### `class asyncio.BoundedSemaphore(value=1, *, loop=None)`228229Реализация ограниченного семафора. Наследуется от [`Semaphore`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore).230231Это возбуждает [`ValueError`](https://python-all.ru/3.6/library/exceptions.html#ValueError) в [`release()`](https://python-all.ru/3.6/library/asyncio-sync.html#asyncio.Semaphore.release), если при этом значение превысило бы начальное значение.232