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 *n* tasks (1 by default) waiting on this 220 condition. If fewer than *n* tasks are waiting they are all awakened. 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 Note that a task *may* return from this call spuriously, 261 which is why the caller should always re-check the state 262 and be prepared to :meth:`~Condition.wait` again. For this reason, you may 263 prefer to use :meth:`~Condition.wait_for` instead. 264 265 .. coroutinemethod:: wait_for(predicate) 266 267 Wait until a predicate becomes *true*. 268 269 The predicate must be a callable which result will be 270 interpreted as a boolean value. The method will repeatedly 271 :meth:`~Condition.wait` until the predicate evaluates to *true*. The final value is the 272 return value. 273 274 275Semaphore 276========= 277 278.. class:: Semaphore(value=1) 279 280 A Semaphore object. Not thread-safe. 281 282 A semaphore manages an internal counter which is decremented by each 283 :meth:`acquire` call and incremented by each :meth:`release` call. 284 The counter can never go below zero; when :meth:`acquire` finds 285 that it is zero, it blocks, waiting until some task calls 286 :meth:`release`. 287 288 The optional *value* argument gives the initial value for the 289 internal counter (``1`` by default). If the given value is 290 less than ``0`` a :exc:`ValueError` is raised. 291 292 .. versionchanged:: 3.10 293 Removed the *loop* parameter. 294 295 The preferred way to use a Semaphore is an :keyword:`async with` 296 statement:: 297 298 sem = asyncio.Semaphore(10) 299 300 # ... later 301 async with sem: 302 # work with shared resource 303 304 which is equivalent to:: 305 306 sem = asyncio.Semaphore(10) 307 308 # ... later 309 await sem.acquire() 310 try: 311 # work with shared resource 312 finally: 313 sem.release() 314 315 .. coroutinemethod:: acquire() 316 317 Acquire a semaphore. 318 319 If the internal counter is greater than zero, decrement 320 it by one and return ``True`` immediately. If it is zero, wait 321 until a :meth:`release` is called and return ``True``. 322 323 .. method:: locked() 324 325 Returns ``True`` if semaphore can not be acquired immediately. 326 327 .. method:: release() 328 329 Release a semaphore, incrementing the internal counter by one. 330 Can wake up a task waiting to acquire the semaphore. 331 332 Unlike :class:`BoundedSemaphore`, :class:`Semaphore` allows 333 making more ``release()`` calls than ``acquire()`` calls. 334 335 336BoundedSemaphore 337================ 338 339.. class:: BoundedSemaphore(value=1) 340 341 A bounded semaphore object. Not thread-safe. 342 343 Bounded Semaphore is a version of :class:`Semaphore` that raises 344 a :exc:`ValueError` in :meth:`~Semaphore.release` if it 345 increases the internal counter above the initial *value*. 346 347 .. versionchanged:: 3.10 348 Removed the *loop* parameter. 349 350 351Barrier 352======= 353 354.. class:: Barrier(parties) 355 356 A barrier object. Not thread-safe. 357 358 A barrier is a simple synchronization primitive that allows to block until 359 *parties* number of tasks are waiting on it. 360 Tasks can wait on the :meth:`~Barrier.wait` method and would be blocked until 361 the specified number of tasks end up waiting on :meth:`~Barrier.wait`. 362 At that point all of the waiting tasks would unblock simultaneously. 363 364 :keyword:`async with` can be used as an alternative to awaiting on 365 :meth:`~Barrier.wait`. 366 367 The barrier can be reused any number of times. 368 369 .. _asyncio_example_barrier: 370 371 Example:: 372 373 async def example_barrier(): 374 # barrier with 3 parties 375 b = asyncio.Barrier(3) 376 377 # create 2 new waiting tasks 378 asyncio.create_task(b.wait()) 379 asyncio.create_task(b.wait()) 380 381 await asyncio.sleep(0) 382 print(b) 383 384 # The third .wait() call passes the barrier 385 await b.wait() 386 print(b) 387 print("barrier passed") 388 389 await asyncio.sleep(0) 390 print(b) 391 392 asyncio.run(example_barrier()) 393 394 Result of this example is:: 395 396 <asyncio.locks.Barrier object at 0x... [filling, waiters:2/3]> 397 <asyncio.locks.Barrier object at 0x... [draining, waiters:0/3]> 398 barrier passed 399 <asyncio.locks.Barrier object at 0x... [filling, waiters:0/3]> 400 401 .. versionadded:: 3.11 402 403 .. coroutinemethod:: wait() 404 405 Pass the barrier. When all the tasks party to the barrier have called 406 this function, they are all unblocked simultaneously. 407 408 When a waiting or blocked task in the barrier is cancelled, 409 this task exits the barrier which stays in the same state. 410 If the state of the barrier is "filling", the number of waiting task 411 decreases by 1. 412 413 The return value is an integer in the range of 0 to ``parties-1``, different 414 for each task. This can be used to select a task to do some special 415 housekeeping, e.g.:: 416 417 ... 418 async with barrier as position: 419 if position == 0: 420 # Only one task prints this 421 print('End of *draining phase*') 422 423 This method may raise a :class:`BrokenBarrierError` exception if the 424 barrier is broken or reset while a task is waiting. 425 It could raise a :exc:`CancelledError` if a task is cancelled. 426 427 .. coroutinemethod:: reset() 428 429 Return the barrier to the default, empty state. Any tasks waiting on it 430 will receive the :class:`BrokenBarrierError` exception. 431 432 If a barrier is broken it may be better to just leave it and create a new one. 433 434 .. coroutinemethod:: abort() 435 436 Put the barrier into a broken state. This causes any active or future 437 calls to :meth:`~Barrier.wait` to fail with the :class:`BrokenBarrierError`. 438 Use this for example if one of the tasks needs to abort, to avoid infinite 439 waiting tasks. 440 441 .. attribute:: parties 442 443 The number of tasks required to pass the barrier. 444 445 .. attribute:: n_waiting 446 447 The number of tasks currently waiting in the barrier while filling. 448 449 .. attribute:: broken 450 451 A boolean that is ``True`` if the barrier is in the broken state. 452 453 454.. exception:: BrokenBarrierError 455 456 This exception, a subclass of :exc:`RuntimeError`, is raised when the 457 :class:`Barrier` object is reset or broken. 458 459--------- 460 461 462.. versionchanged:: 3.9 463 464 Acquiring a lock using ``await lock`` or ``yield from lock`` and/or 465 :keyword:`with` statement (``with await lock``, ``with (yield from 466 lock)``) was removed. Use ``async with lock`` instead. 467