Содержание страницы
18.5.7. Примитивы синхронизации¶Synchronization primitives
Блокировки:
Семафоры:
API блокировок asyncio разработан так, чтобы быть близким к классам модуля threading (Lock, Event, Condition, Semaphore, BoundedSemaphore), но не имеет параметра timeout. Функцию 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, он должен быть объектом Блокировка, который используется в качестве нижележащей блокировки. В противном случае создаётся новый объект Блокировка и используется как нижележащая блокировка.
This class is не является потокобезопасным.
- coroutine acquire()¶
Захватывает базовую блокировку.
Этот метод блокируется, пока блокировка не будет освобождена, затем захватывает её и возвращает True.
Этот метод является корутиной.
- notify(n=1)¶
По умолчанию пробуждает одну корутину, ожидающую на этом условии (если такая есть). Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается RuntimeError.
Этот метод пробуждает не более n корутин, ожидающих переменную условия; он ничего не делает, если никакие корутины не ожидают.
- locked()¶
Возвращает True, если нижележащая блокировка захвачена.
- notify_all()¶
Пробуждает все корутины, ожидающие на этом условии. Этот метод действует как notify(), но пробуждает все ожидающие корутины, а не одну. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается RuntimeError.
- release()¶
Освобождает базовую блокировку.
Когда блокировка заблокирована, сбросить её в разблокированное состояние и вернуться. Если какие-либо другие корутины заблокированы в ожидании разблокировки блокировки, разрешить ровно одной из них продолжить выполнение.
При вызове на незахваченной блокировке возбуждается RuntimeError.
Возвращаемое значение отсутствует.
- coroutine wait()¶
Ожидает уведомления.
Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается RuntimeError.
Этот метод освобождает нижележащую блокировку, а затем блокируется, пока не будет пробуждён вызовом notify() или notify_all() на той же переменной условия в другой корутине. После пробуждения он повторно захватывает блокировку и возвращает True.
Этот метод является корутиной.
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(), если это приведёт к увеличению значения выше начального.