• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
32
33---------
34
35
36Lock
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
99Event
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
171Condition
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
277Semaphore
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
341BoundedSemaphore
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