.. currentmodule:: asyncio
Source code: :source:`Lib/asyncio/locks.py`
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 synchronization primitives:
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()
.. deprecated-removed:: 3.8 3.10 The ``loop`` parameter. This class has been implicitly getting the current running loop since 3.7. See :ref:`What's New in 3.10's Removed section <whatsnew310-removed>` for more information.
.. coroutinemethod:: 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 :meth:`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.
.. 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*.
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:`~Event.set` method and reset to false with the :meth:`clear` method. The :meth:`~Event.wait` method blocks until the flag is set to true. The flag is set to false initially.
.. deprecated-removed:: 3.8 3.10 The ``loop`` parameter. This class has been implicitly getting the current running loop since 3.7. See :ref:`What's New in 3.10's Removed section <whatsnew310-removed>` for more information.
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:`~Event.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:`~Event.wait` will now block until the :meth:`~Event.set` method is called again.
.. method:: is_set() Return ``True`` if the event is set.
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.
.. deprecated-removed:: 3.8 3.10 The ``loop`` parameter. This class has been implicitly getting the current running loop since 3.7. See :ref:`What's New in 3.10's Removed section <whatsnew310-removed>` for more information.
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 cond.acquire()
try:
await cond.wait()
finally:
cond.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.
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.
.. deprecated-removed:: 3.8 3.10 The ``loop`` parameter. This class has been implicitly getting the current running loop since 3.7. See :ref:`What's New in 3.10's Removed section <whatsnew310-removed>` for more information.
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.
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-removed:: 3.8 3.10 The ``loop`` parameter. This class has been implicitly getting the current running loop since 3.7. See :ref:`What's New in 3.10's Removed section <whatsnew310-removed>` for more information.
.. versionchanged:: 3.9 Acquiring a lock using ``await lock`` or ``yield from lock`` and/or :keyword:`with` statement (``with await lock``, ``with (yield from lock)``) was removed. Use ``async with lock`` instead.