Примитивы синхронизации
Исходный код: Lib/asyncio/locks.py
Примитивы синхронизации asyncio разработаны по аналогии с примитивами модуля threading с двумя важными оговорками:
- Примитивы asyncio не являются потокобезопасными, поэтому их не следует использовать для синхронизации потоков ОС (для этого используйте
threading); - методы этих примитивов синхронизации не принимают аргумент timeout; используйте функцию
asyncio.wait_for()для выполнения операций с тайм-аутом.
asyncio предоставляет следующие базовые примитивы синхронизации:
Блокировка
-
class asyncio.Lock(*, loop=None) -
Реализует мьютекс-блокировку для задач asyncio. Не потокобезопасна.
Блокировка asyncio может использоваться для обеспечения исключительного доступа к общему ресурсу.
Предпочтительный способ использования Lock — оператор
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 о том, что произошло какое-то событие.
Объект Event управляет внутренней переменной, которая может быть установлена в истинное значение методом
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 может быть использован задачей для ожидания наступления какого-либо события, а затем для получения исключительного доступа к общему ресурсу.
По сути, объект Condition объединяет функциональность
EventиLock. Возможно использование нескольких объектов Condition с одной блокировкой, что позволяет координировать исключительный доступ к общему ресурсу между различными задачами, заинтересованными в определённых состояниях этого ресурса.Необязательный аргумент lock должен быть объектом
LockилиNone. В последнем случае объект Lock создаётся автоматически.Устарело начиная с версии 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(). После разбуждения Condition снова получает свою блокировку, и этот метод возвращает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.9: Приобретение блокировки с помощью 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.9/library/asyncio-sync.html