18.5.7. Примитивы синхронизации
Исходный код: Lib/asyncio/locks.py
Блокировки:
Семафоры:
API блокировок asyncio спроектирован по аналогии с классами модуля threading (Lock, Event, Condition, Semaphore, BoundedSemaphore), но не имеет параметра тайм-аут. Функция asyncio.wait_for() может использоваться для отмены задачи после тайм-аута.
18.5.7.1. Блокировки
18.5.7.1.1. Блокировка
-
class
asyncio.Lock(*, loop=None)¶ Объекты примитивной блокировки.
Примитивная блокировка – это примитив синхронизации, который не принадлежит какой-либо конкретной корутине, когда заблокирован. Примитивная блокировка находится в одном из двух состояний: «заблокирована» или «разблокирована».
Она создаётся в разблокированном состоянии. У неё есть два основных метода:
acquire()иrelease(). Когда состояние разблокировано, acquire() меняет состояние на заблокированное и немедленно возвращается. Когда состояние заблокировано, acquire() блокируется до тех пор, пока вызов release() в другой корутине не изменит его на разблокированное; затем вызов acquire() сбрасывает его в заблокированное и возвращается. Метод release() следует вызывать только в заблокированном состоянии; он меняет состояние на разблокированное и немедленно возвращается. Если предпринята попытка освободить разблокированную блокировку, будет возбужденоRuntimeError.Когда несколько корутин заблокированы в acquire() в ожидании перехода состояния в разблокированное, только одна корутина продолжает выполнение, когда вызов release() сбрасывает состояние в разблокированное; обрабатывается первая корутина, заблокированная в acquire().
acquire()– корутина, и её следует вызывать сyield from.Блокировки также поддерживают протокол менеджера контекста.
(yield from lock)должен использоваться в качестве выражения менеджера контекста.Этот класс является не потокобезопасным.
Использование:
pythonlock = Lock() ... yield from lock try: ... finally: lock.release()Использование менеджера контекста:
pythonlock = Lock() ... with (yield from lock): ...Объекты блокировки можно проверить на состояние блокировки:
pythonif 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.Этот класс является не потокобезопасным.
-
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и используется в качестве базовой блокировки.Этот класс является не потокобезопасным.
-
coroutine
acquire()¶ Захватить нижележащую блокировку.
Этот метод блокируется до тех пор, пока блокировка не будет разблокирована, затем устанавливает её в заблокированное состояние и возвращает
True.Этот метод является корутиной.
-
notify(n=1)¶ По умолчанию пробуждает одну корутину, ожидающую на этом условии, если таковая есть. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается
RuntimeError.Этот метод пробуждает не более n корутин, ожидающих переменную условия; если ожидающих корутин нет, он ничего не делает.
-
locked()¶ Вернуть
True, если нижележащая блокировка захвачена.
-
notify_all()¶ Пробуждает все корутины, ожидающие на этом условии. Этот метод работает как
notify(), но пробуждает все ожидающие корутины вместо одной. Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждаетсяRuntimeError.
-
release()¶ Освободить нижележащую блокировку.
Если блокировка захвачена, сбрасывает её в незахваченное состояние и возвращает управление. Если какие-либо другие корутины заблокированы в ожидании освобождения блокировки, позволяет ровно одной из них продолжить работу.
При вызове на разблокированной блокировке возбуждается
RuntimeError.Возвращаемое значение отсутствует.
-
coroutine
wait()¶ Ожидать уведомления.
Если вызывающая корутина не захватила блокировку на момент вызова этого метода, возбуждается
RuntimeError.Этот метод освобождает нижележащую блокировку, а затем блокируется до тех пор, пока не будет пробуждён вызовом
notify()илиnotify_all()для той же переменной условия в другой корутине. После пробуждения он повторно захватывает блокировку и возвращаетTrue.Этот метод является корутиной.
-
coroutine
18.5.7.2. Семафоры
18.5.7.2.1. Semaphore
-
class
asyncio.Semaphore(value=1, *, loop=None)¶ Реализация семафора.
Семафор управляет внутренним счётчиком, который уменьшается при каждом вызове
acquire()и увеличивается при каждом вызовеrelease(). Счётчик никогда не может стать меньше нуля; когдаacquire()обнаруживает, что он равен нулю, блокируется в ожидании, пока другая корутина вызоветrelease().Семафоры также поддерживают протокол менеджера контекста.
Необязательный аргумент задаёт начальное значение внутреннего счётчика; по умолчанию
1. Если указанное значение меньше0, возбуждаетсяValueError.Этот класс является не потокобезопасным.
-
coroutine
acquire()¶ Захватить семафор.
Если при входе внутренний счётчик больше нуля, уменьшить его на единицу и немедленно вернуть
True. Если при входе он равен нулю, блокироваться в ожидании, пока другая корутина не вызоветrelease(), чтобы сделать его больше0, после чего вернутьTrue.Этот метод является корутиной.
-
locked()¶ Возвращает
True, если семафор не может быть захвачен немедленно.
-
release()¶ Освобождает семафор, увеличивая внутренний счётчик на единицу. Если при входе он был равен нулю и другая корутина ожидает, пока он снова станет больше нуля, пробудить эту корутину.
-
coroutine
18.5.7.2.2. BoundedSemaphore
-
class
asyncio.BoundedSemaphore(value=1, *, loop=None)¶ Реализация ограниченного семафора. Наследует от
Semaphore.Это возбуждает
ValueErrorвrelease(), если это привело бы к увеличению значения выше начального.