1.. currentmodule:: asyncio
2
3.. _asyncio-sync:
4
5==========================
6Synchronization Primitives
7==========================
8
9**Source code:** :source:`Lib/asyncio/locks.py`
10
11-----------------------------------------------
12
13asyncio synchronization primitives are designed to be similar to
14those 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
24asyncio has the following basic synchronization primitives:
25
26* :class:`Lock`
27* :class:`Event`
28* :class:`Condition`
29* :class:`Semaphore`
30* :class:`BoundedSemaphore`
31* :class:`Barrier`
32
33
34---------
35
36
37Lock
38====
39
40.. class:: Lock()
41
42   Implements a mutex lock for asyncio tasks.  Not thread-safe.
43
44   An asyncio lock can be used to guarantee exclusive access to a
45   shared resource.
46
47   The preferred way to use a Lock is an :keyword:`async with`
48   statement::
49
50       lock = asyncio.Lock()
51
52       # ... later
53       async with lock:
54           # access shared state
55
56   which is equivalent to::
57
58       lock = asyncio.Lock()
59
60       # ... later
61       await lock.acquire()
62       try:
63           # access shared state
64       finally:
65           lock.release()
66
67   .. versionchanged:: 3.10
68      Removed the *loop* parameter.
69
70   .. coroutinemethod:: acquire()
71
72      Acquire the lock.
73
74      This method waits until the lock is *unlocked*, sets it to
75      *locked* and returns ``True``.
76
77      When more than one coroutine is blocked in :meth:`acquire`
78      waiting for the lock to be unlocked, only one coroutine
79      eventually proceeds.
80
81      Acquiring a lock is *fair*: the coroutine that proceeds will be
82      the first coroutine that started waiting on the lock.
83
84   .. method:: release()
85
86      Release the lock.
87
88      When the lock is *locked*, reset it to *unlocked* and return.
89
90      If the lock is *unlocked*, a :exc:`RuntimeError` is raised.
91
92   .. method:: locked()
93
94      Return ``True`` if the lock is *locked*.
95
96
97Event
98=====
99
100.. class:: Event()
101
102   An event object.  Not thread-safe.
103
104   An asyncio event can be used to notify multiple asyncio tasks
105   that some event has happened.
106
107   An Event object manages an internal flag that can be set to *true*
108   with the :meth:`~Event.set` method and reset to *false* with the
109   :meth:`clear` method.  The :meth:`~Event.wait` method blocks until the
110   flag is set to *true*.  The flag is set to *false* initially.
111
112   .. versionchanged:: 3.10
113      Removed the *loop* parameter.
114
115   .. _asyncio_example_sync_event:
116
117   Example::
118
119      async def waiter(event):
120          print('waiting for it ...')
121          await event.wait()
122          print('... got it!')
123
124      async def main():
125          # Create an Event object.
126          event = asyncio.Event()
127
128          # Spawn a Task to wait until 'event' is set.
129          waiter_task = asyncio.create_task(waiter(event))
130
131          # Sleep for 1 second and set the event.
132          await asyncio.sleep(1)
133          event.set()
134
135          # Wait until the waiter task is finished.
136          await waiter_task
137
138      asyncio.run(main())
139
140   .. coroutinemethod:: wait()
141
142      Wait until the event is set.
143
144      If the event is set, return ``True`` immediately.
145      Otherwise block until another task calls :meth:`~Event.set`.
146
147   .. method:: set()
148
149      Set the event.
150
151      All tasks waiting for event to be set will be immediately
152      awakened.
153
154   .. method:: clear()
155
156      Clear (unset) the event.
157
158      Tasks awaiting on :meth:`~Event.wait` will now block until the
159      :meth:`~Event.set` method is called again.
160
161   .. method:: is_set()
162
163      Return ``True`` if the event is set.
164
165
166Condition
167=========
168
169.. class:: Condition(lock=None)
170
171   A Condition object.  Not thread-safe.
172
173   An asyncio condition primitive can be used by a task to wait for
174   some event to happen and then get exclusive access to a shared
175   resource.
176
177   In essence, a Condition object combines the functionality
178   of an :class:`Event` and a :class:`Lock`.  It is possible to have
179   multiple Condition objects share one Lock, which allows coordinating
180   exclusive access to a shared resource between different tasks
181   interested in particular states of that shared resource.
182
183   The optional *lock* argument must be a :class:`Lock` object or
184   ``None``.  In the latter case a new Lock object is created
185   automatically.
186
187   .. versionchanged:: 3.10
188      Removed the *loop* parameter.
189
190   The preferred way to use a Condition is an :keyword:`async with`
191   statement::
192
193       cond = asyncio.Condition()
194
195       # ... later
196       async with cond:
197           await cond.wait()
198
199   which is equivalent to::
200
201       cond = asyncio.Condition()
202
203       # ... later
204       await cond.acquire()
205       try:
206           await cond.wait()
207       finally:
208           cond.release()
209
210   .. coroutinemethod:: acquire()
211
212      Acquire the underlying lock.
213
214      This method waits until the underlying lock is *unlocked*,
215      sets it to *locked* and returns ``True``.
216
217   .. method:: notify(n=1)
218
219      Wake up at most *n* tasks (1 by default) waiting on this
220      condition.  The method is no-op if no tasks are waiting.
221
222      The lock must be acquired before this method is called and
223      released shortly after.  If called with an *unlocked* lock
224      a :exc:`RuntimeError` error is raised.
225
226   .. method:: locked()
227
228      Return ``True`` if the underlying lock is acquired.
229
230   .. method:: notify_all()
231
232      Wake up all tasks waiting on this condition.
233
234      This method acts like :meth:`notify`, but wakes up all waiting
235      tasks.
236
237      The lock must be acquired before this method is called and
238      released shortly after.  If called with an *unlocked* lock
239      a :exc:`RuntimeError` error is raised.
240
241   .. method:: release()
242
243      Release the underlying lock.
244
245      When invoked on an unlocked lock, a :exc:`RuntimeError` is
246      raised.
247
248   .. coroutinemethod:: wait()
249
250      Wait until notified.
251
252      If the calling task has not acquired the lock when this method is
253      called, a :exc:`RuntimeError` is raised.
254
255      This method releases the underlying lock, and then blocks until
256      it is awakened by a :meth:`notify` or :meth:`notify_all` call.
257      Once awakened, the Condition re-acquires its lock and this method
258      returns ``True``.
259
260   .. coroutinemethod:: wait_for(predicate)
261
262      Wait until a predicate becomes *true*.
263
264      The predicate must be a callable which result will be
265      interpreted as a boolean value.  The final value is the
266      return value.
267
268
269Semaphore
270=========
271
272.. class:: Semaphore(value=1)
273
274   A Semaphore object.  Not thread-safe.
275
276   A semaphore manages an internal counter which is decremented by each
277   :meth:`acquire` call and incremented by each :meth:`release` call.
278   The counter can never go below zero; when :meth:`acquire` finds
279   that it is zero, it blocks, waiting until some task calls
280   :meth:`release`.
281
282   The optional *value* argument gives the initial value for the
283   internal counter (``1`` by default). If the given value is
284   less than ``0`` a :exc:`ValueError` is raised.
285
286   .. versionchanged:: 3.10
287      Removed the *loop* parameter.
288
289   The preferred way to use a Semaphore is an :keyword:`async with`
290   statement::
291
292       sem = asyncio.Semaphore(10)
293
294       # ... later
295       async with sem:
296           # work with shared resource
297
298   which is equivalent to::
299
300       sem = asyncio.Semaphore(10)
301
302       # ... later
303       await sem.acquire()
304       try:
305           # work with shared resource
306       finally:
307           sem.release()
308
309   .. coroutinemethod:: acquire()
310
311      Acquire a semaphore.
312
313      If the internal counter is greater than zero, decrement
314      it by one and return ``True`` immediately.  If it is zero, wait
315      until a :meth:`release` is called and return ``True``.
316
317   .. method:: locked()
318
319      Returns ``True`` if semaphore can not be acquired immediately.
320
321   .. method:: release()
322
323      Release a semaphore, incrementing the internal counter by one.
324      Can wake up a task waiting to acquire the semaphore.
325
326      Unlike :class:`BoundedSemaphore`, :class:`Semaphore` allows
327      making more ``release()`` calls than ``acquire()`` calls.
328
329
330BoundedSemaphore
331================
332
333.. class:: BoundedSemaphore(value=1)
334
335   A bounded semaphore object.  Not thread-safe.
336
337   Bounded Semaphore is a version of :class:`Semaphore` that raises
338   a :exc:`ValueError` in :meth:`~Semaphore.release` if it
339   increases the internal counter above the initial *value*.
340
341   .. versionchanged:: 3.10
342      Removed the *loop* parameter.
343
344
345Barrier
346=======
347
348.. class:: Barrier(parties)
349
350   A barrier object.  Not thread-safe.
351
352   A barrier is a simple synchronization primitive that allows to block until
353   *parties* number of tasks are waiting on it.
354   Tasks can wait on the :meth:`~Barrier.wait` method and would be blocked until
355   the specified number of tasks end up waiting on :meth:`~Barrier.wait`.
356   At that point all of the waiting tasks would unblock simultaneously.
357
358   :keyword:`async with` can be used as an alternative to awaiting on
359   :meth:`~Barrier.wait`.
360
361   The barrier can be reused any number of times.
362
363   .. _asyncio_example_barrier:
364
365   Example::
366
367      async def example_barrier():
368         # barrier with 3 parties
369         b = asyncio.Barrier(3)
370
371         # create 2 new waiting tasks
372         asyncio.create_task(b.wait())
373         asyncio.create_task(b.wait())
374
375         await asyncio.sleep(0)
376         print(b)
377
378         # The third .wait() call passes the barrier
379         await b.wait()
380         print(b)
381         print("barrier passed")
382
383         await asyncio.sleep(0)
384         print(b)
385
386      asyncio.run(example_barrier())
387
388   Result of this example is::
389
390      <asyncio.locks.Barrier object at 0x... [filling, waiters:2/3]>
391      <asyncio.locks.Barrier object at 0x... [draining, waiters:0/3]>
392      barrier passed
393      <asyncio.locks.Barrier object at 0x... [filling, waiters:0/3]>
394
395   .. versionadded:: 3.11
396
397   .. coroutinemethod:: wait()
398
399      Pass the barrier. When all the tasks party to the barrier have called
400      this function, they are all unblocked simultaneously.
401
402      When a waiting or blocked task in the barrier is cancelled,
403      this task exits the barrier which stays in the same state.
404      If the state of the barrier is "filling", the number of waiting task
405      decreases by 1.
406
407      The return value is an integer in the range of 0 to ``parties-1``, different
408      for each task. This can be used to select a task to do some special
409      housekeeping, e.g.::
410
411         ...
412         async with barrier as position:
413            if position == 0:
414               # Only one task prints this
415               print('End of *draining phase*')
416
417      This method may raise a :class:`BrokenBarrierError` exception if the
418      barrier is broken or reset while a task is waiting.
419      It could raise a :exc:`CancelledError` if a task is cancelled.
420
421   .. coroutinemethod:: reset()
422
423      Return the barrier to the default, empty state.  Any tasks waiting on it
424      will receive the :class:`BrokenBarrierError` exception.
425
426      If a barrier is broken it may be better to just leave it and create a new one.
427
428   .. coroutinemethod:: abort()
429
430      Put the barrier into a broken state.  This causes any active or future
431      calls to :meth:`wait` to fail with the :class:`BrokenBarrierError`.
432      Use this for example if one of the tasks needs to abort, to avoid infinite
433      waiting tasks.
434
435   .. attribute:: parties
436
437      The number of tasks required to pass the barrier.
438
439   .. attribute:: n_waiting
440
441      The number of tasks currently waiting in the barrier while filling.
442
443   .. attribute:: broken
444
445      A boolean that is ``True`` if the barrier is in the broken state.
446
447
448.. exception:: BrokenBarrierError
449
450   This exception, a subclass of :exc:`RuntimeError`, is raised when the
451   :class:`Barrier` object is reset or broken.
452
453---------
454
455
456.. versionchanged:: 3.9
457
458   Acquiring a lock using ``await lock`` or ``yield from lock`` and/or
459   :keyword:`with` statement (``with await lock``, ``with (yield from
460   lock)``) was removed.  Use ``async with lock`` instead.
461