kbe/src/lib/python/Doc/library/asyncio-sync.rst
.. currentmodule:: asyncio
.. _asyncio-sync:
asyncio synchronization primitives are designed to be similar to
those of the :mod:threading module with two important caveats:
asyncio primitives are not thread-safe, therefore they should not
be used for OS thread synchronization (use :mod:threading for
that);
methods of these synchronization primitives do not accept the timeout
argument; use the :func:asyncio.wait_for function to perform
operations with timeouts.
asyncio has the following basic sychronization primitives:
LockEventConditionSemaphoreBoundedSemaphore.. class:: 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 :keyword:async with
statement::
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()
.. coroutinemethod:: acquire()
Acquire the lock.
This method waits until the lock is *unlocked*, sets it to
*locked* and returns ``True``.
.. method:: release()
Release the lock.
When the lock is *locked*, reset it to *unlocked* and return.
If the lock is *unlocked*, a :exc:`RuntimeError` is raised.
.. method:: locked()
Return ``True`` if the lock is *locked*.
.. class:: 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 :meth:set method and reset to false with the
:meth:clear method. The :meth:wait method blocks until the
flag is set to true. The flag is set to false initially.
.. _asyncio_example_sync_event:
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())
.. coroutinemethod:: wait()
Wait until the event is set.
If the event is set, return ``True`` immediately.
Otherwise block until another task calls :meth:`set`.
.. method:: set()
Set the event.
All tasks waiting for event to be set will be immediately
awakened.
.. method:: clear()
Clear (unset) the event.
Tasks awaiting on :meth:`wait` will now block until the
:meth:`set` method is called again.
.. method:: is_set()
Return ``True`` if the event is set.
.. class:: 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 :class:Event and a :class: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 :class:Lock object or
None. In the latter case a new Lock object is created
automatically.
The preferred way to use a Condition is an :keyword:async with
statement::
cond = asyncio.Condition()
# ... later
async with cond:
await cond.wait()
which is equivalent to::
cond = asyncio.Condition()
# ... later
await lock.acquire()
try:
await cond.wait()
finally:
lock.release()
.. coroutinemethod:: acquire()
Acquire the underlying lock.
This method waits until the underlying lock is *unlocked*,
sets it to *locked* and returns ``True``.
.. method:: 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 :exc:`RuntimeError` error is raised.
.. method:: locked()
Return ``True`` if the underlying lock is acquired.
.. method:: notify_all()
Wake up all tasks waiting on this condition.
This method acts like :meth:`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 :exc:`RuntimeError` error is raised.
.. method:: release()
Release the underlying lock.
When invoked on an unlocked lock, a :exc:`RuntimeError` is
raised.
.. coroutinemethod:: wait()
Wait until notified.
If the calling task has not acquired the lock when this method is
called, a :exc:`RuntimeError` is raised.
This method releases the underlying lock, and then blocks until
it is awakened by a :meth:`notify` or :meth:`notify_all` call.
Once awakened, the Condition re-acquires its lock and this method
returns ``True``.
.. coroutinemethod:: 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.
.. class:: Semaphore(value=1, *, loop=None)
A Semaphore object. Not thread-safe.
A semaphore manages an internal counter which is decremented by each
:meth:acquire call and incremented by each :meth:release call.
The counter can never go below zero; when :meth:acquire finds
that it is zero, it blocks, waiting until some task calls
:meth:release.
The optional value argument gives the initial value for the
internal counter (1 by default). If the given value is
less than 0 a :exc:ValueError is raised.
The preferred way to use a Semaphore is an :keyword:async with
statement::
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()
.. coroutinemethod:: acquire()
Acquire a semaphore.
If the internal counter is greater than zero, decrement
it by one and return ``True`` immediately. If it is zero, wait
until a :meth:`release` is called and return ``True``.
.. method:: locked()
Returns ``True`` if semaphore can not be acquired immediately.
.. method:: release()
Release a semaphore, incrementing the internal counter by one.
Can wake up a task waiting to acquire the semaphore.
Unlike :class:`BoundedSemaphore`, :class:`Semaphore` allows
making more ``release()`` calls than ``acquire()`` calls.
.. class:: BoundedSemaphore(value=1, *, loop=None)
A bounded semaphore object. Not thread-safe.
Bounded Semaphore is a version of :class:Semaphore that raises
a :exc:ValueError in :meth:~Semaphore.release if it
increases the internal counter above the initial value.
.. deprecated:: 3.7
Acquiring a lock using await lock or yield from lock and/or
:keyword:with statement (with await lock, with (yield from lock)) is deprecated. Use async with lock instead.