Spec-Zone.ru › Python 3.7

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

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

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

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

  • Lock
  • Event
  • Condition
  • Semaphore
  • BoundedSemaphore

Блокировка

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()
coroutine acquire()

Получить блокировку.

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

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

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

release()

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

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

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

locked()

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

Событие

class asyncio.Event(*, loop=None)

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

Объект события asyncio может использоваться для уведомления нескольких задач asyncio о том, что какое-то событие произошло.

Объект Event управляет внутренней меткой, которая может быть установлена в true методом set() и сброшена в false методом clear(). Метод wait() блокируется, пока метка не будет установлена в true. По умолчанию метка установлена в false.

Пример:

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.

Предпочтительный способ использования Condition — оператор 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.

Рекомендуемый способ использования семафора — это оператор 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() вызовов.

BoundedSemaphore

class asyncio.BoundedSemaphore(value=1, *, loop=None)

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

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

Устарело начиная с версии 3.7: Получение блокировки с использованием await lock или yield from lock и/или оператора with (with await lock, with (yield from lock)) устарело. Используйте async with lock вместо этого.

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

Spec-Zone.ru

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