@@ -503,62 +503,73 @@ Condition Objects
503503-----------------
504504
505505A condition variable is always associated with some kind of lock; this can be
506- passed in or one will be created by default. (Passing one in is useful when
507- several condition variables must share the same lock.)
508-
509- A condition variable has :meth: `acquire ` and :meth: `release ` methods that call
510- the corresponding methods of the associated lock. It also has a :meth: `wait `
511- method, and :meth: `notify ` and :meth: `notify_all ` methods. These three must only
512- be called when the calling thread has acquired the lock, otherwise a
513- :exc: `RuntimeError ` is raised.
514-
515- The :meth: `wait ` method releases the lock, and then blocks until it is awakened
516- by a :meth: `notify ` or :meth: `notify_all ` call for the same condition variable in
517- another thread. Once awakened, it re-acquires the lock and returns. It is also
518- possible to specify a timeout.
519-
520- The :meth: `notify ` method wakes up one of the threads waiting for the condition
521- variable, if any are waiting. The :meth: `notify_all ` method wakes up all threads
522- waiting for the condition variable.
523-
524- Note: the :meth: `notify ` and :meth: `notify_all ` methods don't release the lock;
525- this means that the thread or threads awakened will not return from their
526- :meth: `wait ` call immediately, but only when the thread that called
527- :meth: `notify ` or :meth: `notify_all ` finally relinquishes ownership of the lock.
528-
529- Tip: the typical programming style using condition variables uses the lock to
506+ passed in or one will be created by default. Passing one in is useful when
507+ several condition variables must share the same lock. The lock is part of
508+ the condition object: you don't have to track it separately.
509+
510+ A condition variable obeys the :term: `context manager ` protocol: using the
511+ ``with `` statement acquires the associated lock for the duration of the
512+ enclosed block. The :meth: `~Condition.acquire ` and :meth: `~Condition.release `
513+ methods also call the corresponding methods of the associated lock.
514+
515+ Other methods must be called with the associated lock held. The
516+ :meth: `~Condition.wait ` method releases the lock, and then blocks until
517+ another thread awakens it by calling :meth: `~Condition.notify ` or
518+ :meth: `~Condition.notify_all `. Once awakened, :meth: `~Condition.wait `
519+ re-acquires the lock and returns. It is also possible to specify a timeout.
520+
521+ The :meth: `~Condition.notify ` method wakes up one of the threads waiting for
522+ the condition variable, if any are waiting. The :meth: `~Condition.notify_all `
523+ method wakes up all threads waiting for the condition variable.
524+
525+ Note: the :meth: `~Condition.notify ` and :meth: `~Condition.notify_all ` methods
526+ don't release the lock; this means that the thread or threads awakened will
527+ not return from their :meth: `~Condition.wait ` call immediately, but only when
528+ the thread that called :meth: `~Condition.notify ` or :meth: `~Condition.notify_all `
529+ finally relinquishes ownership of the lock.
530+
531+
532+ Usage
533+ ^^^^^
534+
535+ The typical programming style using condition variables uses the lock to
530536synchronize access to some shared state; threads that are interested in a
531- particular change of state call :meth: `wait ` repeatedly until they see the
532- desired state, while threads that modify the state call :meth: `notify ` or
533- :meth: `notify_all ` when they change the state in such a way that it could
534- possibly be a desired state for one of the waiters. For example, the following
535- code is a generic producer-consumer situation with unlimited buffer capacity::
537+ particular change of state call :meth: `~Condition.wait ` repeatedly until they
538+ see the desired state, while threads that modify the state call
539+ :meth: `~Condition.notify ` or :meth: `~Condition.notify_all ` when they change
540+ the state in such a way that it could possibly be a desired state for one
541+ of the waiters. For example, the following code is a generic
542+ producer-consumer situation with unlimited buffer capacity::
536543
537544 # Consume one item
538- cv.acquire()
539- while not an_item_is_available():
540- cv.wait()
541- get_an_available_item()
542- cv.release()
545+ with cv:
546+ while not an_item_is_available():
547+ cv.wait()
548+ get_an_available_item()
543549
544550 # Produce one item
545- cv.acquire()
546- make_an_item_available()
547- cv.notify()
548- cv.release()
551+ with cv:
552+ make_an_item_available()
553+
554+ The ``while `` loop checking for the application's condition is necessary
555+ because :meth: `~Condition.wait ` can return after an arbitrary long time,
556+ and other threads may have exhausted the available items in between. This
557+ is inherent to multi-threaded programming. The :meth: `~Condition.wait_for `
558+ method can be used to automate the condition checking::
559+
560+ # Consume an item
561+ with cv:
562+ cv.wait_for(an_item_is_available)
563+ get_an_available_item()
549564
550- To choose between :meth: `notify ` and :meth: `notify_all `, consider whether one
551- state change can be interesting for only one or several waiting threads. E.g.
552- in a typical producer-consumer situation, adding one item to the buffer only
553- needs to wake up one consumer thread.
565+ To choose between :meth: `~Condition. notify ` and :meth: `~Condition. notify_all `,
566+ consider whether one state change can be interesting for only one or several
567+ waiting threads. E.g. in a typical producer-consumer situation, adding one
568+ item to the buffer only needs to wake up one consumer thread.
554569
555- Note: Condition variables can be, depending on the implementation, subject
556- to both spurious wakeups (when :meth: `wait ` returns without a :meth: `notify `
557- call) and stolen wakeups (when another thread acquires the lock before the
558- awoken thread.) For this reason, it is always necessary to verify the state
559- the thread is waiting for when :meth: `wait ` returns and optionally repeat
560- the call as often as necessary.
561570
571+ Interface
572+ ^^^^^^^^^
562573
563574.. class :: Condition(lock=None)
564575
@@ -626,12 +637,6 @@ the call as often as necessary.
626637 held when called and is re-aquired on return. The predicate is evaluated
627638 with the lock held.
628639
629- Using this method, the consumer example above can be written thus::
630-
631- with cv:
632- cv.wait_for(an_item_is_available)
633- get_an_available_item()
634-
635640 .. versionadded :: 3.2
636641
637642 .. method :: notify(n=1)
0 commit comments