Примитивы синхронизации
Исходный код: Lib/asyncio/locks.py
Примитивы синхронизации asyncio предназначены для сходства с примитивами модуля threading с двумя важными оговорками:
- Примитивы asyncio не потокобезопасны, поэтому их не следует использовать для синхронизации потоков ОС (для этого используйте
threading); - методы этих примитивов синхронизации не принимают аргумент timeout; используйте функцию
asyncio.wait_for()для выполнения операций с таймаутами.
asyncio имеет следующие основные примитивы синхронизации:
Блокировка
-
class asyncio.Lock(*, loop=None) -
Реализует мьютекс-блокировку для задач 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.8, будет удалено в версии 3.10: Параметр loop.
-
coroutine acquire() -
Захватить блокировку.
Этот метод ожидает, пока блокировка не будет разблокирована, устанавливает её в заблокированное состояние и возвращает
True.Когда более одной корутины заблокированы в
acquire()в ожидании разблокировки блокировки, только одна корутина в конечном итоге продолжает выполнение.Получение блокировки честное: корутина, которая продолжит работу, будет первой корутиной, которая начала ожидание блокировки.
-
release() -
Освободить блокировку.
Когда блокировка заблокирована, она сбрасывается в разблокированное состояние и возвращается значение.
Если блокировка разблокирована, генерируется исключение
RuntimeError.
-
locked() -
Возвращает
Trueесли блокировка заблокирована.
-
Событие
-
class asyncio.Event(*, loop=None) -
Объект события. Не потокобезопасен.
Объект события asyncio может использоваться для уведомления нескольких задач asyncio о том, что произошло некоторое событие.
Объект события управляет внутренней меткой, которая может быть установлена в истинное значение с помощью метода
set()и сброшена в ложное значение с помощью методаclear(). Методwait()блокирует выполнение, пока метка не будет установлена в истинное значение. Изначально метка имеет значение ложь.Устарело начиная с версии 3.8, будет удалено в версии 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если событие установлено.
-
Условие
-
class asyncio.Condition(lock=None, *, loop=None) -
Объект условия. Не потокобезопасен.
Примитив условия asyncio может использоваться задачей для ожидания наступления некоторого события и последующего получения эксклюзивного доступа к общему ресурсу.
По сути, объект условия объединяет функциональность объекта
EventиLock. Можно иметь несколько объектов условия, использующих одну блокировку, что позволяет координировать эксклюзивный доступ к общему ресурсу между различными задачами, заинтересованными в определенных состояниях этого общего ресурса.Необязательный аргумент lock должен быть объектом
LockилиNone. В последнем случае объект блокировки создаётся автоматически.Устарело начиная с версии 3.8, будет удалено в версии 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) -
Ожидать, пока предикат не станет истинным.
Предикат должен быть вызываемым объектом, результат которого будет интерпретироваться как булево значение. Конечное значение — это возвращаемое значение.
-
Семафор
-
class asyncio.Semaphore(value=1, *, loop=None) -
Объект семафора. Не потокобезопасен.
Семафор управляет внутренней счётчиком, который уменьшается при каждом вызове
acquire()и увеличивается при каждом вызовеrelease(). Счётчик никогда не может опуститься ниже нуля; когдаacquire()обнаруживает, что он равен нулю, он блокируется, ожидая, пока какая-то задача не вызоветrelease().Необязательный аргумент value задаёт начальное значение внутреннего счётчика (по умолчанию
1). Если заданное значение меньше0, генерируется исключениеValueError.Устаревшее с версии 3.8, будет удалено в версии 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()вызовов.
-
Ограниченный семафор
-
class asyncio.BoundedSemaphore(value=1, *, loop=None) -
Объект ограниченного семафора. Не потокобезопасен.
Ограниченный семафор — это версия
Semaphore, которая генерирует исключениеValueErrorвrelease(), если она увеличивает внутренний счётчик выше начального значения value.Устаревшее с версии 3.8, будет удалено в версии 3.10: Параметр loop.
Устаревшее с версии 3.7: Получение блокировки с использованием await lock или yield from lock и/или оператора with (with await lock, with (yield from
lock)) устарело. Используйте async with lock вместо этого.
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/asyncio-sync.html