Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
126aef76
Commit
126aef76
authored
Apr 10, 2012
by
Antoine Pitrou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #8799: Fix and improve the threading.Condition documentation.
parent
88b957a0
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
64 additions
and
54 deletions
+64
-54
Doc/library/threading.rst
Doc/library/threading.rst
+59
-54
Misc/NEWS
Misc/NEWS
+5
-0
No files found.
Doc/library/threading.rst
View file @
126aef76
...
...
@@ -503,62 +503,73 @@ Condition Objects
-----------------
A condition variable is always associated with some kind of lock; this can be
passed in or one will be created by default. (Passing one in is useful when
several condition variables must share the same lock.)
A condition variable has :meth:`acquire` and :meth:`release` methods that call
the corresponding methods of the associated lock. It also has a :meth:`wait`
method, and :meth:`notify` and :meth:`notify_all` methods. These three must only
be called when the calling thread has acquired the lock, otherwise a
:exc:`RuntimeError` is raised.
The :meth:`wait` method releases the lock, and then blocks until it is awakened
by a :meth:`notify` or :meth:`notify_all` call for the same condition variable in
another thread. Once awakened, it re-acquires the lock and returns. It is also
possible to specify a timeout.
The :meth:`notify` method wakes up one of the threads waiting for the condition
variable, if any are waiting. The :meth:`notify_all` method wakes up all threads
waiting for the condition variable.
Note: the :meth:`notify` and :meth:`notify_all` methods don't release the lock;
this means that the thread or threads awakened will not return from their
:meth:`wait` call immediately, but only when the thread that called
:meth:`notify` or :meth:`notify_all` finally relinquishes ownership of the lock.
Tip: the typical programming style using condition variables uses the lock to
passed in or one will be created by default. Passing one in is useful when
several condition variables must share the same lock. The lock is part of
the condition object: you don't have to track it separately.
A condition variable obeys the :term:`context manager` protocol: using the
``with`` statement acquires the associated lock for the duration of the
enclosed block. The :meth:`~Condition.acquire` and :meth:`~Condition.release`
methods also call the corresponding methods of the associated lock.
Other methods must be called with the associated lock held. The
:meth:`~Condition.wait` method releases the lock, and then blocks until
another thread awakens it by calling :meth:`~Condition.notify` or
:meth:`~Condition.notify_all`. Once awakened, :meth:`~Condition.wait`
re-acquires the lock and returns. It is also possible to specify a timeout.
The :meth:`~Condition.notify` method wakes up one of the threads waiting for
the condition variable, if any are waiting. The :meth:`~Condition.notify_all`
method wakes up all threads waiting for the condition variable.
Note: the :meth:`~Condition.notify` and :meth:`~Condition.notify_all` methods
don't release the lock; this means that the thread or threads awakened will
not return from their :meth:`~Condition.wait` call immediately, but only when
the thread that called :meth:`~Condition.notify` or :meth:`~Condition.notify_all`
finally relinquishes ownership of the lock.
Usage
^^^^^
The typical programming style using condition variables uses the lock to
synchronize access to some shared state; threads that are interested in a
particular change of state call :meth:`wait` repeatedly until they see the
desired state, while threads that modify the state call :meth:`notify` or
:meth:`notify_all` when they change the state in such a way that it could
possibly be a desired state for one of the waiters. For example, the following
code is a generic producer-consumer situation with unlimited buffer capacity::
particular change of state call :meth:`~Condition.wait` repeatedly until they
see the desired state, while threads that modify the state call
:meth:`~Condition.notify` or :meth:`~Condition.notify_all` when they change
the state in such a way that it could possibly be a desired state for one
of the waiters. For example, the following code is a generic
producer-consumer situation with unlimited buffer capacity::
# Consume one item
cv.acquire()
while not an_item_is_available():
cv.wait()
get_an_available_item()
cv.release()
with cv:
while not an_item_is_available():
cv.wait()
get_an_available_item()
# Produce one item
cv.acquire()
make_an_item_available()
cv.notify()
cv.release()
with cv:
make_an_item_available()
The ``while`` loop checking for the application's condition is necessary
because :meth:`~Condition.wait` can return after an arbitrary long time,
and other threads may have exhausted the available items in between. This
is inherent to multi-threaded programming. The :meth:`~Condition.wait_for`
method can be used to automate the condition checking::
# Consume an item
with cv:
cv.wait_for(an_item_is_available)
get_an_available_item()
To choose between :meth:`
notify` and :meth:`notify_all`, consider whether one
state change can be interesting for only one or several waiting threads. E.g.
in a typical producer-consumer situation, adding one item to the buffer only
needs to wake up one consumer thread.
To choose between :meth:`
~Condition.notify` and :meth:`~Condition.notify_all`,
consider whether one state change can be interesting for only one or several
waiting threads. E.g. in a typical producer-consumer situation, adding one
item to the buffer only
needs to wake up one consumer thread.
Note: Condition variables can be, depending on the implementation, subject
to both spurious wakeups (when :meth:`wait` returns without a :meth:`notify`
call) and stolen wakeups (when another thread acquires the lock before the
awoken thread.) For this reason, it is always necessary to verify the state
the thread is waiting for when :meth:`wait` returns and optionally repeat
the call as often as necessary.
Interface
^^^^^^^^^
.. class:: Condition(lock=None)
...
...
@@ -626,12 +637,6 @@ the call as often as necessary.
held when called and is re-aquired on return. The predicate is evaluated
with the lock held.
Using this method, the consumer example above can be written thus::
with cv:
cv.wait_for(an_item_is_available)
get_an_available_item()
.. versionadded:: 3.2
.. method:: notify(n=1)
...
...
Misc/NEWS
View file @
126aef76
...
...
@@ -138,6 +138,11 @@ Build
- Issue #14359: Only use O_CLOEXEC in _posixmodule.c if it is defined.
Based on patch from Hervé Coatanhay.
Documentation
-------------
- Issue #8799: Fix and improve the threading.Condition documentation.
What's New in Python 3.2.3 release candidate 2?
===============================================
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment