Примитивы синхронизации
Примитивы синхронизации asyncio разработаны по аналогии с примитивами модуля threading с двумя важными оговорками:
- Примитивы asyncio не являются потокобезопасными, поэтому их не следует использовать для синхронизации ОС-потоков (используйте
threadingдля этой цели); - методы этих примитивов синхронизации не принимают аргумент timeout; используйте функцию
asyncio.wait_for()для выполнения операций с таймаутами.
asyncio предоставляет следующие базовые примитивы синхронизации:
Блокировка
-
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