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(\*, loop=None) 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. 68 69 .. coroutinemethod:: acquire() 70 71 Acquire the lock. 72 73 This method waits until the lock is *unlocked*, sets it to 74 *locked* and returns ``True``. 75 76 When more than one coroutine is blocked in :meth:`acquire` 77 waiting for the lock to be unlocked, only one coroutine 78 eventually proceeds. 79 80 Acquiring a lock is *fair*: the coroutine that proceeds will be 81 the first coroutine that started waiting on the lock. 82 83 .. method:: release() 84 85 Release the lock. 86 87 When the lock is *locked*, reset it to *unlocked* and return. 88 89 If the lock is *unlocked*, a :exc:`RuntimeError` is raised. 90 91 .. method:: locked() 92 93 Return ``True`` if the lock is *locked*. 94 95 96Event 97===== 98 99.. class:: Event(\*, loop=None) 100 101 An event object. Not thread-safe. 102 103 An asyncio event can be used to notify multiple asyncio tasks 104 that some event has happened. 105 106 An Event object manages an internal flag that can be set to *true* 107 with the :meth:`~Event.set` method and reset to *false* with the 108 :meth:`clear` method. The :meth:`~Event.wait` method blocks until the 109 flag is set to *true*. The flag is set to *false* initially. 110 111 112 .. deprecated-removed:: 3.8 3.10 113 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, \*, loop=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 188 .. deprecated-removed:: 3.8 3.10 189 The *loop* parameter. 190 191 The preferred way to use a Condition is an :keyword:`async with` 192 statement:: 193 194 cond = asyncio.Condition() 195 196 # ... later 197 async with cond: 198 await cond.wait() 199 200 which is equivalent to:: 201 202 cond = asyncio.Condition() 203 204 # ... later 205 await cond.acquire() 206 try: 207 await cond.wait() 208 finally: 209 cond.release() 210 211 .. coroutinemethod:: acquire() 212 213 Acquire the underlying lock. 214 215 This method waits until the underlying lock is *unlocked*, 216 sets it to *locked* and returns ``True``. 217 218 .. method:: notify(n=1) 219 220 Wake up at most *n* tasks (1 by default) waiting on this 221 condition. The method is no-op if no tasks are waiting. 222 223 The lock must be acquired before this method is called and 224 released shortly after. If called with an *unlocked* lock 225 a :exc:`RuntimeError` error is raised. 226 227 .. method:: locked() 228 229 Return ``True`` if the underlying lock is acquired. 230 231 .. method:: notify_all() 232 233 Wake up all tasks waiting on this condition. 234 235 This method acts like :meth:`notify`, but wakes up all waiting 236 tasks. 237 238 The lock must be acquired before this method is called and 239 released shortly after. If called with an *unlocked* lock 240 a :exc:`RuntimeError` error is raised. 241 242 .. method:: release() 243 244 Release the underlying lock. 245 246 When invoked on an unlocked lock, a :exc:`RuntimeError` is 247 raised. 248 249 .. coroutinemethod:: wait() 250 251 Wait until notified. 252 253 If the calling task has not acquired the lock when this method is 254 called, a :exc:`RuntimeError` is raised. 255 256 This method releases the underlying lock, and then blocks until 257 it is awakened by a :meth:`notify` or :meth:`notify_all` call. 258 Once awakened, the Condition re-acquires its lock and this method 259 returns ``True``. 260 261 .. coroutinemethod:: wait_for(predicate) 262 263 Wait until a predicate becomes *true*. 264 265 The predicate must be a callable which result will be 266 interpreted as a boolean value. The final value is the 267 return value. 268 269 270Semaphore 271========= 272 273.. class:: Semaphore(value=1, \*, loop=None) 274 275 A Semaphore object. Not thread-safe. 276 277 A semaphore manages an internal counter which is decremented by each 278 :meth:`acquire` call and incremented by each :meth:`release` call. 279 The counter can never go below zero; when :meth:`acquire` finds 280 that it is zero, it blocks, waiting until some task calls 281 :meth:`release`. 282 283 The optional *value* argument gives the initial value for the 284 internal counter (``1`` by default). If the given value is 285 less than ``0`` a :exc:`ValueError` is raised. 286 287 288 .. deprecated-removed:: 3.8 3.10 289 The *loop* parameter. 290 291 The preferred way to use a Semaphore is an :keyword:`async with` 292 statement:: 293 294 sem = asyncio.Semaphore(10) 295 296 # ... later 297 async with sem: 298 # work with shared resource 299 300 which is equivalent to:: 301 302 sem = asyncio.Semaphore(10) 303 304 # ... later 305 await sem.acquire() 306 try: 307 # work with shared resource 308 finally: 309 sem.release() 310 311 .. coroutinemethod:: acquire() 312 313 Acquire a semaphore. 314 315 If the internal counter is greater than zero, decrement 316 it by one and return ``True`` immediately. If it is zero, wait 317 until a :meth:`release` is called and return ``True``. 318 319 .. method:: locked() 320 321 Returns ``True`` if semaphore can not be acquired immediately. 322 323 .. method:: release() 324 325 Release a semaphore, incrementing the internal counter by one. 326 Can wake up a task waiting to acquire the semaphore. 327 328 Unlike :class:`BoundedSemaphore`, :class:`Semaphore` allows 329 making more ``release()`` calls than ``acquire()`` calls. 330 331 332BoundedSemaphore 333================ 334 335.. class:: BoundedSemaphore(value=1, \*, loop=None) 336 337 A bounded semaphore object. Not thread-safe. 338 339 Bounded Semaphore is a version of :class:`Semaphore` that raises 340 a :exc:`ValueError` in :meth:`~Semaphore.release` if it 341 increases the internal counter above the initial *value*. 342 343 344 .. deprecated-removed:: 3.8 3.10 345 The *loop* parameter. 346 347--------- 348 349 350.. deprecated:: 3.7 351 352 Acquiring a lock using ``await lock`` or ``yield from lock`` and/or 353 :keyword:`with` statement (``with await lock``, ``with (yield from 354 lock)``) is deprecated. Use ``async with lock`` instead. 355