asyncio-sync.md · Markdown – Документация Python
Документация Python неофициальный перевод

asyncio-sync.md

273 строк · 15.5 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.7/library/asyncio-sync.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Примитивы синхронизации89Примитивы синхронизации asyncio устроены аналогично примитивам модуля [`threading`](https://python-all.ru/3.7/library/threading.html#module-threading), но с двумя важными оговорками:1011- Примитивы asyncio не являются потокобезопасными, поэтому их не следует использовать для синхронизации потоков ОС (для этого используйте [`threading`](https://python-all.ru/3.7/library/threading.html#module-threading));12- Методы этих примитивов синхронизации не принимают аргумент *timeout*; для выполнения операций с таймаутами используйте функцию [`asyncio.wait_for()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.wait_for).1314В asyncio имеются следующие базовые примитивы синхронизации:1516- [`Lock`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Lock)17- [`Event`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Event)18- [`Condition`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Condition)19- [`Semaphore`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Semaphore)20- [`BoundedSemaphore`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.BoundedSemaphore)2122---2324## Блокировка2526#### `class asyncio.Lock(*, loop=None)`2728Реализует блокировку мьютекса для задач asyncio. Не потокобезопасна.2930Блокировка asyncio может использоваться для обеспечения исключительного доступа к общему ресурсу.3132The preferred way to use a Lock is an [`async with`](https://python-all.ru/3.7/reference/compound_stmts.html#async-with) statement:3334```python35lock = asyncio.Lock()3637# ... позже38async with lock:39    # доступ к общему состоянию40```4142это эквивалентно следующему:4344```python45lock = asyncio.Lock()4647# ... позже48await lock.acquire()49try:50    # доступ к общему состоянию51finally:52    lock.release()53```5455#### `coroutine acquire()`5657Захватывает блокировку.5859Этот метод ожидает, пока блокировка не будет *разблокирована*, переводит её в состояние *заблокирована* и возвращает `True`.6061Если несколько корутин заблокированы вызовом [`acquire()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Lock.acquire) в ожидании разблокировки блокировки, только одна из них в итоге продолжит выполнение.6263Захват блокировки *справедлив*: выполнение продолжит первая корутина, начавшая ожидание блокировки.6465#### `release()`6667Освобождает блокировку.6869Если блокировка *заблокирована*, сбрасывает её в состояние *разблокирована* и завершается.7071Если блокировка *разблокирована*, возбуждается исключение [`RuntimeError`](https://python-all.ru/3.7/library/exceptions.html#RuntimeError).7273#### `locked()`7475Возвращает `True`, если блокировка *заблокирована*.7677## Event7879#### `class asyncio.Event(*, loop=None)`8081Объект события. Не потокобезопасен.8283Событие asyncio может использоваться для оповещения нескольких задач asyncio о наступлении некоторого события.8485Объект Event управляет внутренним флагом, который может быть установлен в *true* методом [`set()`](https://python-all.ru/3.7/library/stdtypes.html#set) и сброшен в *false* методом [`clear()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Event.clear). Метод [`wait()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.wait) блокируется, пока флаг не будет установлен в *true*. Изначально флаг установлен в *false*.8687Пример:8889```python90async def waiter(event):91    print('waiting for it ...')92    await event.wait()93    print('... got it!')9495async def main():96    # Создать объект Event.97    event = asyncio.Event()9899    # Создать задачу, ожидающую установки 'event'.100    waiter_task = asyncio.create_task(waiter(event))101102    # Подождать 1 секунду и установить событие.103    await asyncio.sleep(1)104    event.set()105106    # Дождаться завершения ожидающей задачи.107    await waiter_task108109asyncio.run(main())110```111112#### `coroutine wait()`113114Ожидает, пока событие не будет установлено.115116Если событие установлено, немедленно возвращает `True`. В противном случае блокируется до тех пор, пока другая задача не вызовет [`set()`](https://python-all.ru/3.7/library/stdtypes.html#set).117118#### `set()`119120Устанавливает событие.121122Все задачи, ожидающие установки события, будут немедленно пробуждены.123124#### `clear()`125126Сбрасывает (снимает) событие.127128Задачи, ожидающие на [`wait()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.wait), теперь будут блокироваться, пока метод [`set()`](https://python-all.ru/3.7/library/stdtypes.html#set) не будет вызван снова.129130#### `is_set()`131132Возвращает `True`, если событие установлено.133134## Condition135136#### `class asyncio.Condition(lock=None, *, loop=None)`137138Объект Condition. Не потокобезопасен.139140Примитив условия asyncio позволяет задаче дождаться наступления некоторого события, а затем получить исключительный доступ к общему ресурсу.141142По сути, объект Condition объединяет функциональность [`Event`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Event) и [`Lock`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Lock). Несколько объектов Condition могут совместно использовать одну блокировку, что позволяет координировать исключительный доступ к общему ресурсу между различными задачами, заинтересованными в определённых состояниях этого ресурса.143144Необязательный аргумент *блокировка* должен быть объектом [`Lock`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Lock) или `None`. В последнем случае новый объект блокировки создаётся автоматически.145146Предпочтительный способ использования Condition – оператор [`async with`](https://python-all.ru/3.7/reference/compound_stmts.html#async-with):147148```python149cond = asyncio.Condition()150151# ... позже152async with cond:153    await cond.wait()154```155156это эквивалентно следующему:157158```python159cond = asyncio.Condition()160161# ... позже162await cond.acquire()163try:164    await cond.wait()165finally:166    cond.release()167```168169#### `coroutine acquire()`170171Захватывает базовую блокировку.172173Этот метод ожидает, пока базовая блокировка не будет *разблокирована*, устанавливает её в состояние *заблокирована* и возвращает `True`.174175#### `notify(n=1)`176177Будит не более *n* задач (по умолчанию 1), ожидающих на этом условии. Если ожидающих задач нет, метод ничего не делает.178179Блокировка должна быть захвачена до вызова этого метода и освобождена сразу после. Если вызвать с *разблокированной* блокировкой, будет возбуждено исключение [`RuntimeError`](https://python-all.ru/3.7/library/exceptions.html#RuntimeError).180181#### `locked()`182183Возвращает `True`, если базовая блокировка захвачена.184185#### `notify_all()`186187Пробуждает все задачи, ожидающие данное условие.188189Этот метод действует как [`notify()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Condition.notify), но пробуждает все ожидающие задачи.190191Блокировка должна быть захвачена до вызова этого метода и освобождена сразу после. Если вызвать с *разблокированной* блокировкой, будет возбуждено исключение [`RuntimeError`](https://python-all.ru/3.7/library/exceptions.html#RuntimeError).192193#### `release()`194195Освобождает базовую блокировку.196197При вызове на незаблокированной блокировке возникает [`RuntimeError`](https://python-all.ru/3.7/library/exceptions.html#RuntimeError).198199#### `coroutine wait()`200201Ожидает уведомления.202203Если вызывающая задача не захватила блокировку на момент вызова этого метода, возникает [`RuntimeError`](https://python-all.ru/3.7/library/exceptions.html#RuntimeError).204205Этот метод освобождает базовую блокировку и блокируется до тех пор, пока не будет пробуждён вызовом [`notify()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Condition.notify) или [`notify_all()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Condition.notify_all). После пробуждения условие снова захватывает свою блокировку, и метод возвращает `True`.206207#### `coroutine wait_for(predicate)`208209Ожидает, пока предикат не станет *истинным*.210211Предикат должен быть вызываемым объектом, результат которого будет интерпретирован как булево значение. Конечное значение – это возвращаемое значение.212213## Semaphore214215#### `class asyncio.Semaphore(value=1, *, loop=None)`216217Объект семафора. Не потокобезопасен.218219Семафор управляет внутренним счётчиком, который уменьшается при каждом вызове [`acquire()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Semaphore.acquire) и увеличивается при каждом вызове [`release()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Semaphore.release). Счётчик никогда не может стать меньше нуля; когда [`acquire()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Semaphore.acquire) обнаруживает, что он равен нулю, он блокируется в ожидании, пока какая-либо задача не вызовет [`release()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Semaphore.release).220221Необязательный аргумент *value* задаёт начальное значение внутреннего счётчика (по умолчанию `1`). Если переданное значение меньше `0`, возникает [`ValueError`](https://python-all.ru/3.7/library/exceptions.html#ValueError).222223Предпочтительный способ использования семафора – оператор [`async with`](https://python-all.ru/3.7/reference/compound_stmts.html#async-with):224225```python226sem = asyncio.Semaphore(10)227228# ... позже229async with sem:230    # работать с общим ресурсом231```232233это эквивалентно следующему:234235```python236sem = asyncio.Semaphore(10)237238# ... позже239await sem.acquire()240try:241    # работать с общим ресурсом242finally:243    sem.release()244```245246#### `coroutine acquire()`247248Захватывает семафор.249250Если внутренний счётчик больше нуля, уменьшить его на единицу и немедленно вернуть `True`. Если он равен нулю, ждать, пока не будет вызван [`release()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Semaphore.release), и вернуть `True`.251252#### `locked()`253254Возвращает `True`, если семафор не может быть захвачен немедленно.255256#### `release()`257258Освобождает семафор, увеличивая внутренний счётчик на единицу. Может пробудить задачу, ожидающую захвата семафора.259260В отличие от [`BoundedSemaphore`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.BoundedSemaphore), [`Semaphore`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Semaphore) допускает больше вызовов `release()`, чем вызовов `acquire()`.261262## BoundedSemaphore263264#### `class asyncio.BoundedSemaphore(value=1, *, loop=None)`265266Объект ограниченного семафора. Не потокобезопасен.267268Bounded Semaphore – это версия [`Semaphore`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Semaphore), которая возбуждает [`ValueError`](https://python-all.ru/3.7/library/exceptions.html#ValueError) в [`release()`](https://python-all.ru/3.7/library/asyncio-sync.html#asyncio.Semaphore.release), если увеличивает внутренний счётчик выше начального *value*.269270---271272Устарело с версии 3.7: Получение блокировки с помощью `await lock` или `yield from lock` и/или [`with`](https://python-all.ru/3.7/reference/compound_stmts.html#with) (`with await lock`, `with (yield from lock)`) устарело. Вместо этого используйте `async with lock`.273