Документация Python неофициальный перевод
Содержание страницы

18.5.7. Примитивы синхронизацииSynchronization primitives

Блокировки:

Семафоры:

API блокировок asyncio было разработано так, чтобы быть близким к классам модуля threading (Lock, Event, Condition, Semaphore, BoundedSemaphore), но у него нет параметра тайм-аут. Функция asyncio.wait_for() может использоваться для отмены задачи по тайм-ауту.

18.5.7.1. БлокировкиLocks

18.5.7.1.1. БлокировкаLock

class asyncio.Lock(*, loop=None)

Объекты примитивных блокировок.

Примитивная блокировка – это примитив синхронизации, который не принадлежит конкретной корутине, когда заблокирован. Примитивная блокировка находится в одном из двух состояний: «locked» или «unlocked».

Она создаётся в разблокированном состоянии. У неё есть два основных метода: acquire() и release(). Когда состояние разблокировано, acquire() изменяет состояние на заблокированное и возвращается немедленно. Когда состояние заблокировано, acquire() блокируется до тех пор, пока вызов release() в другой корутине не изменит его на разблокированное, затем вызов acquire() сбрасывает его в заблокированное и возвращается. Метод release() следует вызывать только в заблокированном состоянии; он изменяет состояние на разблокированное и возвращается немедленно. При попытке освободить разблокированную блокировку будет возбуждено исключение RuntimeError.

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

acquire() является корутиной и должна вызываться с yield from.

Блокировки также поддерживают протокол менеджера контекста. (yield from lock) следует использовать в качестве выражения менеджера контекста.

This class is не является потокобезопасным.

Использование:

lock = Lock()
...
yield from lock
try:
    ...
finally:
    lock.release()

Использование менеджера контекста:

lock = Lock()
...
with (yield from lock):
    ...

Объекты блокировки можно проверить на состояние блокировки:

if not lock.locked():
    yield from lock
else:
    # блокировка получена
    ...
locked()

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

coroutine acquire()

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

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

Этот метод является корутиной.

release()

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

Когда блокировка заблокирована, сбросить её в разблокированное состояние и вернуться. Если какие-либо другие корутины заблокированы в ожидании разблокировки блокировки, позволить ровно одной из них продолжить.

При вызове на не заблокированной блокировке возбуждается исключение RuntimeError.

Возвращаемое значение отсутствует.

18.5.7.1.2. Event

class asyncio.Event(*, loop=None)

Реализация Event, асинхронный эквивалент threading.Event.

Класс, реализующий объекты событий. Событие управляет флагом, который может быть установлен в true с помощью метода set() и сброшен в false с помощью метода clear(). Метод wait() блокируется до тех пор, пока флаг не станет true. Изначально флаг установлен в false.

This class is не является потокобезопасным.

clear()

Сбросить внутренний флаг в false. После этого корутины, вызывающие wait(), будут блокироваться до тех пор, пока не будет вызван set() для повторной установки внутреннего флага в true.

is_set()

Возвращает True тогда и только тогда, когда внутренний флаг равен true.

set()

Установить внутренний флаг в true. Все корутины, ожидающие его перехода в true, пробуждаются. Корутины, вызывающие wait() после того, как флаг станет true, не будут блокироваться вообще.

coroutine wait()

Блокироваться до тех пор, пока внутренний флаг не станет true.

Если внутренний флаг уже true при входе, немедленно вернуть True. В противном случае блокироваться до тех пор, пока другая корутина не вызовет set(), чтобы установить флаг в true, затем вернуть True.

Этот метод является корутиной.

18.5.7.1.3. Condition

class asyncio.Condition(lock=None, *, loop=None)

Реализация Condition, асинхронный эквивалент threading.Condition.

Этот класс реализует объекты переменных условия. Переменная условия позволяет одной или нескольким корутинам ожидать, пока они не будут уведомлены другой корутиной.

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

This class is не является потокобезопасным.

coroutine acquire()

Захватывает базовую блокировку.

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

Этот метод является корутиной.

notify(n=1)

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

Этот метод пробуждает не более n корутин, ожидающих переменную условия; он ничего не делает, если никакие корутины не ожидают.

Примечание

Пробуждённая корутина на самом деле не возвращается из своего вызова wait() до тех пор, пока не сможет повторно захватить блокировку. Поскольку notify() не освобождает блокировку, это должен сделать её вызывающая сторона.

locked()

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

notify_all()

Пробуждает все корутины, ожидающие на этом условии. Этот метод действует как notify(), но пробуждает все ожидающие корутины вместо одной. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается RuntimeError.

release()

Освобождает базовую блокировку.

Когда блокировка заблокирована, сбросить её в разблокированное состояние и вернуться. Если какие-либо другие корутины заблокированы в ожидании разблокировки блокировки, разрешить ровно одной из них продолжить выполнение.

При вызове на не заблокированной блокировке возбуждается исключение RuntimeError.

Возвращаемое значение отсутствует.

coroutine wait()

Ожидает уведомления.

Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается RuntimeError.

Этот метод освобождает нижележащую блокировку, а затем блокирует выполнение до тех пор, пока он не будет пробуждён вызовом notify() или notify_all() для той же переменной условия в другой корутине. После пробуждения он повторно захватывает блокировку и возвращает True.

Этот метод является корутиной.

coroutine wait_for(predicate)

Ожидает, пока предикат не станет истинным.

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

Этот метод является корутиной.

18.5.7.2. СемафорыSemaphores

18.5.7.2.1. Semaphore

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

Реализация семафора.

Семафор управляет внутренним счётчиком, который уменьшается при каждом вызове acquire() и увеличивается при каждом вызове release(). Счётчик никогда не может опуститься ниже нуля; когда acquire() обнаруживает, что он равен нулю, он блокирует выполнение, ожидая, пока какая-либо другая корутина вызовет release().

Семафоры также поддерживают протокол управления контекстом.

Необязательный аргумент задаёт начальное значение внутреннего счётчика; по умолчанию он равен 1. Если указанное значение меньше 0, возбуждается ValueError.

This class is не является потокобезопасным.

coroutine acquire()

Захватывает семафор.

Если внутренний счётчик больше нуля на входе, уменьшить его на единицу и немедленно вернуть True. Если он равен нулю на входе, заблокировать выполнение, ожидая, пока какая-либо другая корутина вызовет release(), чтобы сделать его больше чем 0, а затем вернуть True.

Этот метод является корутиной.

locked()

Возвращает True, если семафор не может быть захвачен немедленно.

release()

Освободить семафор, увеличивая внутренний счётчик на единицу. Если он был равен нулю на входе и другая корутина ожидает, пока он снова станет больше нуля, пробудить эту корутину.

18.5.7.2.2. BoundedSemaphore

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

Реализация ограниченного семафора. Наследуется от Semaphore.

Это возбуждает ValueError в release(), если при этом значение превысило бы начальное значение.