Synchronization Primitives¶
asyncio synchronization primitives are designed to be similar to
those of the threading module with two important caveats:
- asyncio primitives are not thread-safe, therefore they should not be used for OS thread synchronization (use - threadingfor that);
- methods of these synchronization primitives do not accept the timeout argument; use the - asyncio.wait_for()function to perform operations with timeouts.
asyncio has the following basic synchronization primitives:
Lock¶
- 
class asyncio.Lock(*, loop=None)¶
- Implements a mutex lock for asyncio tasks. Not thread-safe. - An asyncio lock can be used to guarantee exclusive access to a shared resource. - The preferred way to use a Lock is an - async withstatement:- lock = asyncio.Lock() # ... later async with lock: # access shared state - which is equivalent to: - lock = asyncio.Lock() # ... later await lock.acquire() try: # access shared state finally: lock.release() - 
coroutine acquire()¶
- Acquire the lock. - This method waits until the lock is unlocked, sets it to locked and returns - True.- When more than one coroutine is blocked in - acquire()waiting for the lock to be unlocked, only one coroutine eventually proceeds.- Acquiring a lock is fair: the coroutine that proceeds will be the first coroutine that started waiting on the lock. 
 - 
release()¶
- Release the lock. - When the lock is locked, reset it to unlocked and return. - If the lock is unlocked, a - RuntimeErroris raised.
 - 
locked()¶
- Return - Trueif the lock is locked.
 
- 
coroutine 
Event¶
- 
class asyncio.Event(*, loop=None)¶
- An event object. Not thread-safe. - An asyncio event can be used to notify multiple asyncio tasks that some event has happened. - An Event object manages an internal flag that can be set to true with the - set()method and reset to false with the- clear()method. The- wait()method blocks until the flag is set to true. The flag is set to false initially.- Example: - 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()¶
- Wait until the event is set. - If the event is set, return - Trueimmediately. Otherwise block until another task calls- set().
 - 
set()¶
- Set the event. - All tasks waiting for event to be set will be immediately awakened. 
 - 
clear()¶
- Clear (unset) the event. - Tasks awaiting on - wait()will now block until the- set()method is called again.
 - 
is_set()¶
- Return - Trueif the event is set.
 
- 
coroutine 
Condition¶
- 
class asyncio.Condition(lock=None, *, loop=None)¶
- A Condition object. Not thread-safe. - An asyncio condition primitive can be used by a task to wait for some event to happen and then get exclusive access to a shared resource. - In essence, a Condition object combines the functionality of an - Eventand a- Lock. It is possible to have multiple Condition objects share one Lock, which allows coordinating exclusive access to a shared resource between different tasks interested in particular states of that shared resource.- The optional lock argument must be a - Lockobject or- None. In the latter case a new Lock object is created automatically.- The preferred way to use a Condition is an - async withstatement:- cond = asyncio.Condition() # ... later async with cond: await cond.wait() - which is equivalent to: - cond = asyncio.Condition() # ... later await cond.acquire() try: await cond.wait() finally: cond.release() - 
coroutine acquire()¶
- Acquire the underlying lock. - This method waits until the underlying lock is unlocked, sets it to locked and returns - True.
 - 
notify(n=1)¶
- Wake up at most n tasks (1 by default) waiting on this condition. The method is no-op if no tasks are waiting. - The lock must be acquired before this method is called and released shortly after. If called with an unlocked lock a - RuntimeErrorerror is raised.
 - 
locked()¶
- Return - Trueif the underlying lock is acquired.
 - 
notify_all()¶
- Wake up all tasks waiting on this condition. - This method acts like - notify(), but wakes up all waiting tasks.- The lock must be acquired before this method is called and released shortly after. If called with an unlocked lock a - RuntimeErrorerror is raised.
 - 
release()¶
- Release the underlying lock. - When invoked on an unlocked lock, a - RuntimeErroris raised.
 - 
coroutine wait()¶
- Wait until notified. - If the calling task has not acquired the lock when this method is called, a - RuntimeErroris raised.- This method releases the underlying lock, and then blocks until it is awakened by a - notify()or- notify_all()call. Once awakened, the Condition re-acquires its lock and this method returns- True.
 - 
coroutine wait_for(predicate)¶
- Wait until a predicate becomes true. - The predicate must be a callable which result will be interpreted as a boolean value. The final value is the return value. 
 
- 
coroutine 
Semaphore¶
- 
class asyncio.Semaphore(value=1, *, loop=None)¶
- A Semaphore object. Not thread-safe. - A semaphore manages an internal counter which is decremented by each - acquire()call and incremented by each- release()call. The counter can never go below zero; when- acquire()finds that it is zero, it blocks, waiting until some task calls- release().- The optional value argument gives the initial value for the internal counter ( - 1by default). If the given value is less than- 0a- ValueErroris raised.- The preferred way to use a Semaphore is an - async withstatement:- sem = asyncio.Semaphore(10) # ... later async with sem: # work with shared resource - which is equivalent to: - sem = asyncio.Semaphore(10) # ... later await sem.acquire() try: # work with shared resource finally: sem.release() - 
coroutine acquire()¶
- Acquire a semaphore. - If the internal counter is greater than zero, decrement it by one and return - Trueimmediately. If it is zero, wait until a- release()is called and return- True.
 - 
locked()¶
- Returns - Trueif semaphore can not be acquired immediately.
 - 
release()¶
- Release a semaphore, incrementing the internal counter by one. Can wake up a task waiting to acquire the semaphore. - Unlike - BoundedSemaphore,- Semaphoreallows making more- release()calls than- acquire()calls.
 
- 
coroutine 
BoundedSemaphore¶
- 
class asyncio.BoundedSemaphore(value=1, *, loop=None)¶
- A bounded semaphore object. Not thread-safe. - Bounded Semaphore is a version of - Semaphorethat raises a- ValueErrorin- release()if it increases the internal counter above the initial value.
Deprecated since version 3.7: Acquiring a lock using await lock or yield from lock and/or
with statement (with await lock, with (yield from
lock)) is deprecated.  Use async with lock instead.
