Примитивы синхронизации¶
Исходный код: Lib/asyncio/locks.py.
Примитивы синхронизации asyncio разработаны так, чтобы быть похожими на примитивы модуля threading с двумя важными оговорками:
- Примитивы asyncio не являются потокобезопасными, поэтому их не следует использовать для синхронизации потоков ОС (для этого используйте - threading);
- методы этих примитивов синхронизации не принимают аргумент timeout; для выполнения операций с таймаутами используйте функцию - asyncio.wait_for().
asyncio имеет следующие основные примитивы синхронизации:
Замок¶
- 
class asyncio.Lock¶
- Реализует мьютексную блокировку для задач asyncio. Не является потокобезопасным. - Блокировка asyncio может быть использована для обеспечения эксклюзивного доступа к общему ресурсу. - Предпочтительным способом использования блокировки является оператор - async with:- lock = asyncio.Lock() # ... later async with lock: # access shared state - что эквивалентно: - lock = asyncio.Lock() # ... later await lock.acquire() try: # access shared state finally: lock.release() - Изменено в версии 3.10: Удален параметр loop. - 
coroutine acquire()¶
- Приобретите замок. - Этот метод ждет, пока блокировка не будет разблокирована, устанавливает ее в заблокирована и возвращает - True.- Когда несколько программ блокируются в - acquire()в ожидании разблокировки блокировки, в конечном итоге выполняется только одна программа.- Получение блокировки является справедливым: выполняемая программа будет первой программой, которая начала ожидать блокировку. 
 - 
release()¶
- Освободите замок. - Когда замок заблокирован, сбросьте его на разблокирован и вернитесь. - Если блокировка разблокирована, возникает ошибка - RuntimeError.
 - 
locked()¶
- Возвращает - True, если замок заблокирован.
 
- 
coroutine 
Событие¶
- 
class asyncio.Event¶
- Объект события. Не является потокобезопасным. - Событие asyncio можно использовать для уведомления нескольких задач asyncio о том, что произошло какое-то событие. - Объект Event управляет внутренним флагом, который может быть установлен в значение true методом - set()и сброшен в значение false методом- clear(). Метод- wait()блокируется до тех пор, пока флаг не будет установлен в значение true. Изначально флаг устанавливается в false.- Изменено в версии 3.10: Удален параметр loop. - Пример: - async def waiter(event): print('waiting for it ...') await event.wait() print('... got it!') async def main(): # Create an Event object. event = asyncio.Event() # Spawn a Task to wait until 'event' is set. waiter_task = asyncio.create_task(waiter(event)) # Sleep for 1 second and set the event. await asyncio.sleep(1) event.set() # Wait until the waiter task is finished. await waiter_task asyncio.run(main()) - 
coroutine wait()¶
- Подождите, пока событие не будет установлено. - Если событие установлено, немедленно верните - True. В противном случае блокируйте до тех пор, пока другая задача не вызовет- set().
 - 
set()¶
- Установите событие. - Все задачи, ожидающие наступления события, будут немедленно пробуждены. 
 - 
clear()¶
- Очистить (снять установку) событие. - Задачи, ожидающие на - wait(), теперь будут блокироваться до тех пор, пока метод- set()не будет вызван снова.
 - 
is_set()¶
- Возвращает - True, если событие установлено.
 
- 
coroutine 
Состояние¶
- 
class asyncio.Condition(lock=None)¶
- Объект Condition. Не является потокобезопасным. - Примитив условия asyncio может быть использован задачей для ожидания некоторого события и последующего получения эксклюзивного доступа к общему ресурсу. - По сути, объект Condition сочетает в себе функциональность - Eventи- Lock. Возможно, чтобы несколько объектов Condition совместно использовали один Lock, что позволяет координировать эксклюзивный доступ к общему ресурсу между различными задачами, заинтересованными в определенных состояниях этого общего ресурса.- Необязательный аргумент lock должен быть объектом - Lockили- None. В последнем случае новый объект Lock создается автоматически.- Изменено в версии 3.10: Удален параметр loop. - Предпочтительным способом использования условия является оператор - async with:- cond = asyncio.Condition() # ... later async with cond: await cond.wait() - что эквивалентно: - cond = asyncio.Condition() # ... later await cond.acquire() try: await cond.wait() finally: cond.release() - 
coroutine acquire()¶
- Приобретите базовую блокировку. - Этот метод ждет, пока базовая блокировка не будет разблокирована, устанавливает ее в блокирована и возвращает - True.
 - 
notify(n=1)¶
- Пробудить не более n задач (по умолчанию 1), ожидающих выполнения данного условия. Метод не работает, если ни одна задача не ожидает. - Блокировка должна быть получена до вызова этого метода и освобождена вскоре после него. Если метод вызывается с незаблокированной блокировкой, будет выдана ошибка - RuntimeError.
 - 
locked()¶
- Возвращает - True, если базовая блокировка получена.
 - 
notify_all()¶
- Разбудите все задачи, ожидающие этого условия. - Этот метод действует аналогично - notify(), но пробуждает все ожидающие задачи.- Блокировка должна быть получена до вызова этого метода и освобождена вскоре после него. Если метод вызывается с незаблокированной блокировкой, будет выдана ошибка - RuntimeError.
 - 
release()¶
- Освободите основную блокировку. - При вызове на разблокированной блокировке возникает ошибка - RuntimeError.
 - 
coroutine wait()¶
- Дождитесь уведомления. - Если вызывающая задача не получила блокировку на момент вызова этого метода, будет вызвана ошибка - RuntimeError.- Этот метод освобождает основную блокировку, а затем блокирует ее до тех пор, пока она не будет разбужена вызовом - notify()или- notify_all(). После пробуждения условие вновь приобретает свою блокировку, и этот метод возвращает- True.
 - 
coroutine wait_for(predicate)¶
- Подождите, пока предикат станет истинным. - Предикат должен быть вызываемой переменной, результат которой будет интерпретирован как булево значение. Конечное значение - это возвращаемое значение. 
 
- 
coroutine 
Семафор¶
- 
class asyncio.Semaphore(value=1)¶
- Объект семафора. Не является потокобезопасным. - Семафор управляет внутренним счетчиком, который уменьшается при каждом вызове - acquire()и увеличивается при каждом вызове- release(). Счетчик никогда не может опуститься ниже нуля; когда- acquire()обнаруживает, что он равен нулю, он блокируется, ожидая, пока какая-нибудь задача не вызовет- release().- Необязательный аргумент value задает начальное значение для внутреннего счетчика (по умолчанию - 1). Если заданное значение меньше, чем- 0, то возникает ошибка- ValueError.- Изменено в версии 3.10: Удален параметр loop. - Предпочтительным способом использования семафора является оператор - async with:- sem = asyncio.Semaphore(10) # ... later async with sem: # work with shared resource - что эквивалентно: - sem = asyncio.Semaphore(10) # ... later await sem.acquire() try: # work with shared resource finally: sem.release() - 
coroutine acquire()¶
- Приобретите семафор. - Если внутренний счетчик больше нуля, уменьшите его на единицу и немедленно верните - True. Если он равен нулю, дождитесь вызова- release()и верните- True.
 - 
locked()¶
- Возвращает - True, если семафор не может быть получен немедленно.
 - 
release()¶
- Освобождает семафор, увеличивая внутренний счетчик на единицу. Может разбудить задачу, ожидающую получения семафора. - В отличие от - BoundedSemaphore,- Semaphoreпозволяет делать больше вызовов- release(), чем вызовов- acquire().
 
- 
coroutine 
BoundedSemaphore¶
- 
class asyncio.BoundedSemaphore(value=1)¶
- Ограниченный объект семафора. Не является потокобезопасным. - Bounded Semaphore - это версия - Semaphore, которая поднимает- ValueErrorв- release(), если увеличивает внутренний счетчик выше начального значения.- Изменено в версии 3.10: Удален параметр loop. 
Изменено в версии 3.9: Приобретение блокировки с помощью оператора await lock или yield from lock и/или with (with await lock, with (yield from lock)) было удалено.  Вместо этого используйте async with lock.