Примитивы синхронизации¶
Исходный код: Lib/asyncio/locks.py
Примитивы синхронизации asyncio разработаны так, чтобы они были аналогичны
примитивам модуля threading
с двумя важными предостережения:
- asyncio примитивы не являются потокобезопасной, поэтому их не следует используемый
для синхронизации потоков ОС (для этого используйте
threading
); - методы из этих примитивов синхронизации не принимают аргумент timeout;
используйте функцию
asyncio.wait_for()
для выполнения операций с таймаутами.
asyncio имеет следующие основные примитивы синхронизации:
Блокировки¶
-
class
asyncio.
Lock
(*, loop=None)¶ Реализует блокировку mutex для asyncio задач. Не потокобезопасной.
Для обеспечения исключительного доступа к совместно используемому ресурсу можно asyncio используемый блокировку.
Предпочтительным способом использования блокировки является
async with
оператор:lock = asyncio.Lock() # ... позже async with lock: # доступ к общему состоянию
Что эквивалентно:
lock = asyncio.Lock() # ... позже await lock.acquire() try: # доступ к общему состоянию finally: lock.release()
Deprecated since version 3.8, will be removed in version 3.10: Параметр loop.
-
coroutine
acquire
()¶ Установить блокировку.
Этот метод ждет, пока блокировка не unlocked, наборы он к locked и возвращаетs
True
.Когда в
acquire()
блокируется более одного корутина, ожидающего разблокирования замка, в конечном счете продолжается только один корутин.Приобретение замка - это fair: корутин, который идет, будет первым корутином, который начал ждать на замке.
-
release
()¶ Отпустить блокировку.
После locked блокировки Установить ее в unlocked и возвращает.
Если блокировка unlocked, то поднимается
RuntimeError
.
-
locked
()¶ Возвращает
True
, если блокировка locked.
-
coroutine
Событие¶
-
class
asyncio.
Event
(*, loop=None)¶ Объект событий. Не потокобезопасной.
Событие asyncio может быть используемый для уведомления нескольких asyncio задач о том, что произошло какое-либо событие.
Объект Event управляет внутренним флагом, который может быть установлен в true с помощью метода
set()
и сброшен в false с помощью методаclear()
. Методwait()
блокируется, пока для флага не будет установлено значение true. Первоначально флаг установлен в false.Deprecated since version 3.8, will be removed in version 3.10: Параметр loop.
Пример:
async def waiter(event): print('waiting for it ...') await event.wait() print('... got it!') async def main(): # Создайте объект Event. event = asyncio.Event() # Создать задачу, чтобы подождать, пока не будет установлено "событие2. waiter_task = asyncio.create_task(waiter(event)) # Спать в течение 1 секунды и установить событие. await asyncio.sleep(1) event.set() # Подождите, пока официант не закончит свою работу. await waiter_task asyncio.run(main())
-
coroutine
wait
()¶ Дождаться завершения установки события.
Если событие установлено, немедленно вернуть
True
. В противном случае блокируйте, пока другая задача не вызоветset()
.
-
set
()¶ Установить событие.
Все задачи, ожидающие задания события, будут немедленно пробуждены.
-
clear
()¶ Очистить (отменить) событие.
Задачи, ожидающие на
wait()
, теперь будут блокироваться до тех пор, пока методset()
не будет повторно вызван.
-
is_set
()¶ Возвращает
True
, если событие установлено.
-
coroutine
Состояние¶
-
class
asyncio.
Condition
(lock=None, *, loop=None)¶ Объект условия. Не потокобезопасной.
Примитив условия asyncio может быть используемый задачей, чтобы дождаться события и получить монопольный доступ к общему ресурсу.
По существу, объект Condition объединяет функциональные возможности
Event
иLock
. Возможно наличие нескольких объектов Condition совместно использующих один Lock, что позволяет координировать монопольный доступ к совместно используемому ресурсу между различными задачами, интересующими определенные состояниеs этого совместно используемого ресурса.Необязательный аргумент lock должен быть объектом
Lock
илиNone
. В последнем случае новый объект Lock создается автоматически.Deprecated since version 3.8, will be removed in version 3.10: Параметр loop.
Предпочтительным способом использования условия является
async with
оператор:cond = asyncio.Condition() # ... позже async with cond: await cond.wait()
Что эквивалентно:
cond = asyncio.Condition() # ... позже await cond.acquire() try: await cond.wait() finally: cond.release()
-
coroutine
acquire
()¶ Получить основную блокировку.
Этот метод ожидает unlocked базовой блокировки, устанавливает ее в locked и возвращает
True
.
-
notify
(n=1)¶ Не более n задач (по умолчанию 1), ожидающих выполнения этого условия. Если задачи не ожидаются, метод не выполняется.
блокировка должен быть получен до вызова этого метод и разблокирован вскоре после этого. При вызове с блокировкой unlocked возникает
RuntimeError
ошибка.
-
locked
()¶ Возвращает
True
, будет ли получена соответствующая блокировка.
-
notify_all
()¶ Пробуждение всех задач, ожидающих выполнения этого условия.
Этот метод действует как
notify()
, но просыпает все ожидающие задания.Блокировка должен быть получен до вызова этого метод и разблокирован вскоре после этого. При вызове с блокировкой unlocked возникает
RuntimeError
ошибка.
-
release
()¶ Разблокируйте основной блокировка.
При вызове при разблокированной блокировке возникает
RuntimeError
.
-
coroutine
wait
()¶ Жать, пока не зарегистрировано.
Если вызывающая задача не получила блокировку при вызове этого метод, возникает
RuntimeError
.Этот метод освобождает основную блокировку, а затем блокирует ее до тех пор, пока она не будет пробуждена
notify()
илиnotify_all()
вызовом. После пробуждения условие вновь приобретает свой блокировка и это метод возвращаетsTrue
.
-
coroutine
wait_for
(predicate)¶ Додаться true predicate.
predicate должен быть вызываемым, результат которого будет интерпретироваться как логическое значение. Конечное значение является возвращает значением.
-
coroutine
Семафор¶
-
class
asyncio.
Semaphore
(value=1, *, loop=None)¶ Объект семафора. Не потокобезопасной.
Семафор управляет внутренним счетчиком, который уменьшается при каждом
acquire()
вызове и увеличивается при каждомrelease()
вызове. Счетчик никогда не может быть ниже нуля; когдаacquire()
обнаруживает, что оно равно нулю, он блокируется, ожидая, пока какая-то задача не вызоветrelease()
.Необязательный аргумент value дает начальное значение для внутреннего счетчика (
1
по умолчанию). Если заданное значение меньше0
возникаетValueError
.Deprecated since version 3.8, will be removed in version 3.10: Параметр loop.
Предпочтительным способом использования семафора является
async with
оператор:sem = asyncio.Semaphore(10) # ... later async with sem: # работа с разделяемым ресурсом
Что эквивалентно:
sem = asyncio.Semaphore(10) # ... позже await sem.acquire() try: # работа с разделяемым ресурсом finally: sem.release()
-
coroutine
acquire
()¶ Установка семафора.
Если внутренний счетчик больше нуля, уменьшите его на один и возвращает
True
немедленно. Если оно равно нулю, дождитесь вызоваrelease()
и возвращаетTrue
.
-
locked
()¶ Возвращает
True
, если семафор не может быть получен немедленно.
-
release
()¶ Освобождение семафора, увеличив внутренний счетчик на единицу. Может пробудить задачу, ожидающую получения семафора.
В отличие от
BoundedSemaphore
,Semaphore
позволяет совершать большеrelease()
вызовов, чемacquire()
.
-
coroutine
BoundedSemaphore¶
-
class
asyncio.
BoundedSemaphore
(value=1, *, loop=None)¶ Ограниченный семафорный объект. Не потокобезопасной.
Ограниченный семафор - версия
Semaphore
, поднимающаяValueError
вrelease()
, если она увеличивает внутренний счетчик выше начального value.Deprecated since version 3.8, will be removed in version 3.10: Параметр loop.
Не рекомендуется, начиная с версии 3.7: Использование блокировки, используя await lock
или yield from lock
и/или with
оператор (with await lock
, with (yield from lock)
) запрещено. Используйте async with lock
вместо этого.