A condition variable is always associated with some kind of lock;this can be passed in or one will be created by default. (Passingone in is useful when several condition variables must share thesame lock.)
A condition variable hasacquire() andrelease()methods that call the corresponding methods of the associated lock.It also has await() method, andnotify() andnotifyAll() methods. These three must only be called whenthe calling thread has acquired the lock.
Thewait() method releases the lock, and then blocks until itis awakened by anotify() ornotifyAll() call forthe same condition variable in another thread. Once awakened, itre-acquires the lock and returns. It is also possible to specify atimeout.
Thenotify() method wakes up one of the threads waiting forthe condition variable, if any are waiting. ThenotifyAll()method wakes up all threads waiting for the condition variable.
Note: thenotify() andnotifyAll() methods don'trelease the lock; this means that the thread or threads awakened willnot return from theirwait() call immediately, but only whenthe thread that callednotify() ornotifyAll()finally relinquishes ownership of the lock.
Tip: the typical programming style using condition variables uses thelock to synchronize access to some shared state; threads that areinterested in a particular change of state callwait()repeatedly until they see the desired state, while threads that modifythe state callnotify() ornotifyAll() when theychange the state in such a way that it could possibly be a desiredstate for one of the waiters. For example, the following code is ageneric producer-consumer situation with unlimited buffer capacity:
# Consume one itemcv.acquire()while not an_item_is_available(): cv.wait()get_an_available_item()cv.release()# Produce one itemcv.acquire()make_an_item_available()cv.notify()cv.release()
To choose betweennotify() andnotifyAll(), considerwhether one state change can be interesting for only one or severalwaiting threads. E.g. in a typical producer-consumer situation,adding one item to the buffer only needs to wake up one consumerthread.
| [lock]) |
None, it must be aLock orRLock object, and it is used as the underlyinglock. Otherwise, a newRLock object is created and used asthe underlying lock.| *args) |
| ) |
| [timeout]) |
This method releases the underlying lock, and then blocks until it isawakened by anotify() ornotifyAll() call for thesame condition variable in another thread, or until the optionaltimeout occurs. Once awakened or timed out, it re-acquires the lockand returns.
When thetimeout argument is present and notNone, itshould be a floating point number specifying a timeout for theoperation in seconds (or fractions thereof).
When the underlying lock is anRLock, it is not released usingitsrelease() method, since this may not actually unlock thelock when it was acquired multiple times recursively. Instead, aninternal interface of theRLock class is used, which reallyunlocks it even when it has been recursively acquired several times.Another internal interface is then used to restore the recursion levelwhen the lock is reacquired.
| ) |
This method wakes up one of the threads waiting for the conditionvariable, if any are waiting; it is a no-op if no threads are waiting.
The current implementation wakes up exactly one thread, if any arewaiting. However, it's not safe to rely on this behavior. A future,optimized implementation may occasionally wake up more than onethread.
Note: the awakened thread does not actually return from itswait() call until it can reacquire the lock. Sincenotify() does not release the lock, its caller should.
| ) |