• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 .. currentmodule:: asyncio
2 
3 .. _asyncio-sync:
4 
5 ==========================
6 Synchronization Primitives
7 ==========================
8 
9 **Source code:** :source:`Lib/asyncio/locks.py`
10 
11 -----------------------------------------------
12 
13 asyncio synchronization primitives are designed to be similar to
14 those of the :mod:`threading` module with two important caveats:
15 
16 * asyncio primitives are not thread-safe, therefore they should not
17   be used for OS thread synchronization (use :mod:`threading` for
18   that);
19 
20 * methods of these synchronization primitives do not accept the *timeout*
21   argument; use the :func:`asyncio.wait_for` function to perform
22   operations with timeouts.
23 
24 asyncio has the following basic synchronization primitives:
25 
26 * :class:`Lock`
27 * :class:`Event`
28 * :class:`Condition`
29 * :class:`Semaphore`
30 * :class:`BoundedSemaphore`
31 
32 
33 ---------
34 
35 
36 Lock
37 ====
38 
39 .. class:: Lock()
40 
41    Implements a mutex lock for asyncio tasks.  Not thread-safe.
42 
43    An asyncio lock can be used to guarantee exclusive access to a
44    shared resource.
45 
46    The preferred way to use a Lock is an :keyword:`async with`
47    statement::
48 
49        lock = asyncio.Lock()
50 
51        # ... later
52        async with lock:
53            # access shared state
54 
55    which is equivalent to::
56 
57        lock = asyncio.Lock()
58 
59        # ... later
60        await lock.acquire()
61        try:
62            # access shared state
63        finally:
64            lock.release()
65 
66    .. deprecated-removed:: 3.8 3.10
67       The ``loop`` parameter.  This class has been implicitly getting the
68       current running loop since 3.7.  See
69       :ref:`What's New in 3.10's Removed section <whatsnew310-removed>`
70       for more information.
71 
72    .. coroutinemethod:: acquire()
73 
74       Acquire the lock.
75 
76       This method waits until the lock is *unlocked*, sets it to
77       *locked* and returns ``True``.
78 
79       When more than one coroutine is blocked in :meth:`acquire`
80       waiting for the lock to be unlocked, only one coroutine
81       eventually proceeds.
82 
83       Acquiring a lock is *fair*: the coroutine that proceeds will be
84       the first coroutine that started waiting on the lock.
85 
86    .. method:: release()
87 
88       Release the lock.
89 
90       When the lock is *locked*, reset it to *unlocked* and return.
91 
92       If the lock is *unlocked*, a :exc:`RuntimeError` is raised.
93 
94    .. method:: locked()
95 
96       Return ``True`` if the lock is *locked*.
97 
98 
99 Event
100 =====
101 
102 .. class:: Event()
103 
104    An event object.  Not thread-safe.
105 
106    An asyncio event can be used to notify multiple asyncio tasks
107    that some event has happened.
108 
109    An Event object manages an internal flag that can be set to *true*
110    with the :meth:`~Event.set` method and reset to *false* with the
111    :meth:`clear` method.  The :meth:`~Event.wait` method blocks until the
112    flag is set to *true*.  The flag is set to *false* initially.
113 
114    .. deprecated-removed:: 3.8 3.10
115       The ``loop`` parameter.  This class has been implicitly getting the
116       current running loop since 3.7.  See
117       :ref:`What's New in 3.10's Removed section <whatsnew310-removed>`
118       for more information.
119 
120    .. _asyncio_example_sync_event:
121 
122    Example::
123 
124       async def waiter(event):
125           print('waiting for it ...')
126           await event.wait()
127           print('... got it!')
128 
129       async def main():
130           # Create an Event object.
131           event = asyncio.Event()
132 
133           # Spawn a Task to wait until 'event' is set.
134           waiter_task = asyncio.create_task(waiter(event))
135 
136           # Sleep for 1 second and set the event.
137           await asyncio.sleep(1)
138           event.set()
139 
140           # Wait until the waiter task is finished.
141           await waiter_task
142 
143       asyncio.run(main())
144 
145    .. coroutinemethod:: wait()
146 
147       Wait until the event is set.
148 
149       If the event is set, return ``True`` immediately.
150       Otherwise block until another task calls :meth:`~Event.set`.
151 
152    .. method:: set()
153 
154       Set the event.
155 
156       All tasks waiting for event to be set will be immediately
157       awakened.
158 
159    .. method:: clear()
160 
161       Clear (unset) the event.
162 
163       Tasks awaiting on :meth:`~Event.wait` will now block until the
164       :meth:`~Event.set` method is called again.
165 
166    .. method:: is_set()
167 
168       Return ``True`` if the event is set.
169 
170 
171 Condition
172 =========
173 
174 .. class:: Condition(lock=None)
175 
176    A Condition object.  Not thread-safe.
177 
178    An asyncio condition primitive can be used by a task to wait for
179    some event to happen and then get exclusive access to a shared
180    resource.
181 
182    In essence, a Condition object combines the functionality
183    of an :class:`Event` and a :class:`Lock`.  It is possible to have
184    multiple Condition objects share one Lock, which allows coordinating
185    exclusive access to a shared resource between different tasks
186    interested in particular states of that shared resource.
187 
188    The optional *lock* argument must be a :class:`Lock` object or
189    ``None``.  In the latter case a new Lock object is created
190    automatically.
191 
192    .. deprecated-removed:: 3.8 3.10
193       The ``loop`` parameter.  This class has been implicitly getting the
194       current running loop since 3.7.  See
195       :ref:`What's New in 3.10's Removed section <whatsnew310-removed>`
196       for more information.
197 
198    The preferred way to use a Condition is an :keyword:`async with`
199    statement::
200 
201        cond = asyncio.Condition()
202 
203        # ... later
204        async with cond:
205            await cond.wait()
206 
207    which is equivalent to::
208 
209        cond = asyncio.Condition()
210 
211        # ... later
212        await cond.acquire()
213        try:
214            await cond.wait()
215        finally:
216            cond.release()
217 
218    .. coroutinemethod:: acquire()
219 
220       Acquire the underlying lock.
221 
222       This method waits until the underlying lock is *unlocked*,
223       sets it to *locked* and returns ``True``.
224 
225    .. method:: notify(n=1)
226 
227       Wake up at most *n* tasks (1 by default) waiting on this
228       condition.  The method is no-op if no tasks are waiting.
229 
230       The lock must be acquired before this method is called and
231       released shortly after.  If called with an *unlocked* lock
232       a :exc:`RuntimeError` error is raised.
233 
234    .. method:: locked()
235 
236       Return ``True`` if the underlying lock is acquired.
237 
238    .. method:: notify_all()
239 
240       Wake up all tasks waiting on this condition.
241 
242       This method acts like :meth:`notify`, but wakes up all waiting
243       tasks.
244 
245       The lock must be acquired before this method is called and
246       released shortly after.  If called with an *unlocked* lock
247       a :exc:`RuntimeError` error is raised.
248 
249    .. method:: release()
250 
251       Release the underlying lock.
252 
253       When invoked on an unlocked lock, a :exc:`RuntimeError` is
254       raised.
255 
256    .. coroutinemethod:: wait()
257 
258       Wait until notified.
259 
260       If the calling task has not acquired the lock when this method is
261       called, a :exc:`RuntimeError` is raised.
262 
263       This method releases the underlying lock, and then blocks until
264       it is awakened by a :meth:`notify` or :meth:`notify_all` call.
265       Once awakened, the Condition re-acquires its lock and this method
266       returns ``True``.
267 
268    .. coroutinemethod:: wait_for(predicate)
269 
270       Wait until a predicate becomes *true*.
271 
272       The predicate must be a callable which result will be
273       interpreted as a boolean value.  The final value is the
274       return value.
275 
276 
277 Semaphore
278 =========
279 
280 .. class:: Semaphore(value=1)
281 
282    A Semaphore object.  Not thread-safe.
283 
284    A semaphore manages an internal counter which is decremented by each
285    :meth:`acquire` call and incremented by each :meth:`release` call.
286    The counter can never go below zero; when :meth:`acquire` finds
287    that it is zero, it blocks, waiting until some task calls
288    :meth:`release`.
289 
290    The optional *value* argument gives the initial value for the
291    internal counter (``1`` by default). If the given value is
292    less than ``0`` a :exc:`ValueError` is raised.
293 
294    .. deprecated-removed:: 3.8 3.10
295       The ``loop`` parameter.  This class has been implicitly getting the
296       current running loop since 3.7.  See
297       :ref:`What's New in 3.10's Removed section <whatsnew310-removed>`
298       for more information.
299 
300    The preferred way to use a Semaphore is an :keyword:`async with`
301    statement::
302 
303        sem = asyncio.Semaphore(10)
304 
305        # ... later
306        async with sem:
307            # work with shared resource
308 
309    which is equivalent to::
310 
311        sem = asyncio.Semaphore(10)
312 
313        # ... later
314        await sem.acquire()
315        try:
316            # work with shared resource
317        finally:
318            sem.release()
319 
320    .. coroutinemethod:: acquire()
321 
322       Acquire a semaphore.
323 
324       If the internal counter is greater than zero, decrement
325       it by one and return ``True`` immediately.  If it is zero, wait
326       until a :meth:`release` is called and return ``True``.
327 
328    .. method:: locked()
329 
330       Returns ``True`` if semaphore can not be acquired immediately.
331 
332    .. method:: release()
333 
334       Release a semaphore, incrementing the internal counter by one.
335       Can wake up a task waiting to acquire the semaphore.
336 
337       Unlike :class:`BoundedSemaphore`, :class:`Semaphore` allows
338       making more ``release()`` calls than ``acquire()`` calls.
339 
340 
341 BoundedSemaphore
342 ================
343 
344 .. class:: BoundedSemaphore(value=1)
345 
346    A bounded semaphore object.  Not thread-safe.
347 
348    Bounded Semaphore is a version of :class:`Semaphore` that raises
349    a :exc:`ValueError` in :meth:`~Semaphore.release` if it
350    increases the internal counter above the initial *value*.
351 
352    .. deprecated-removed:: 3.8 3.10
353 
354       The ``loop`` parameter.  This class has been implicitly getting the
355       current running loop since 3.7.  See
356       :ref:`What's New in 3.10's Removed section <whatsnew310-removed>`
357       for more information.
358 
359 ---------
360 
361 
362 .. versionchanged:: 3.9
363 
364    Acquiring a lock using ``await lock`` or ``yield from lock`` and/or
365    :keyword:`with` statement (``with await lock``, ``with (yield from
366    lock)``) was removed.  Use ``async with lock`` instead.
367