Spec-Zone.ru › Python 3.10

Примитивы синхронизации

Исходный код: Lib/asyncio/locks.py

Примитивы синхронизации asyncio разработаны, чтобы быть похожими на примитивы модуля threading с двумя важными оговорками:

  • Примитивы asyncio не являются потокобезопасными, поэтому их не следует использовать для синхронизации потоков ОС (для этого используйте threading);
  • методы этих примитивов синхронизации не принимают аргумент timeout; для выполнения операций с таймаутами используйте функцию asyncio.wait_for().

asyncio имеет следующие базовые примитивы синхронизации:

  • Lock
  • Event
  • Condition
  • Semaphore
  • BoundedSemaphore

Блокировка

class asyncio.Lock

Реализует блокировку взаимного исключения для задач 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.10: Параметр loop удален.

coroutine acquire()

Захватить блокировку.

Этот метод ожидает, пока блокировка не будет разблокирована, устанавливает её в заблокированное состояние и возвращает True.

Когда более одной сопрограммы заблокированы в acquire() в ожидании разблокировки, только одна сопрограмма в конечном итоге продолжает выполнение.

Получение блокировки справедливо: сопрограмма, которая продолжит выполнение, будет первой сопрограммой, которая начала ожидание блокировки.

release()

Освободить блокировку.

Когда блокировка заблокирована, она устанавливается в разблокированное состояние и возвращается значение.

Если блокировка разблокирована, генерируется исключение RuntimeError.

locked()

Возвращает True, если блокировка заблокирована.

Событие

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, если событие установлено.

Условие

class asyncio.Condition(lock=None)

Объект условия. Не потокобезопасен.

Примитив условия asyncio может использоваться задачей для ожидания наступления события и последующего получения эксклюзивного доступа к общему ресурсу.

По сути, объект условия объединяет функциональность объекта Event и блокировки Lock. Возможна ситуация, когда несколько объектов Condition используют одну блокировку, что позволяет координировать эксклюзивный доступ к общему ресурсу между различными задачами, заинтересованными в определённых состояниях этого общего ресурса.

Необязательный аргумент lock должен быть объектом Lock или None. В последнем случае объект блокировки создаётся автоматически.

Изменено в версии 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)

Ожидать, пока предикат не станет true.

Предикат должен быть вызываемым, результат которого будет интерпретироваться как булево значение. Конечное значение — это возвращаемое значение.

END_OF_DOCUMENT_MARKER

Семафор

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() вызовов.

Ограниченный семафор

class asyncio.BoundedSemaphore(value=1)

Объект ограниченного семафора. Не потокобезопасен.

Ограниченный семафор — это версия Semaphore, которая возбуждает исключение ValueError при вызове release(), если она увеличивает внутреннюю счётную переменную выше начального значения value.

Изменено в версии 3.10: Параметр loop удалён.

Изменено в версии 3.9: Захват блокировки с помощью await lock или yield from lock и/или оператора with (with await lock, with (yield from lock)) был удалён. Используйте async with lock вместо этого.

© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/library/asyncio-sync.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API