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