Robert Strandh writes:
I am having a hard time understanding condition variables.
By providing an atomic "release lock and sleep" operation, a condition variable guards against the "lost notification" problem, which is where the writer adds data to the buffer in between the time that a reader tests it (finding it empty) and goes to sleep.
I do not see how having a "release lock and sleep" operation fixes the "lost notification" problem. Who would use the operation? The reader or the writer or both?
The common use case is like this:
(defun reader () (with-lock-held (*lock*) (loop (condition-wait *condvar* *lock*) (when <something there> <consume>))))
(defun writer () (loop (with-lock-held (*lock*) <add something to be consumed> (condition-notify *condvar*))))
The notification cannot be lost since entering CONDITION-WAIT is while the lock is held at which point the writer cannot have it. Only after things are set up within the deep magic of CONDITION-WAIT to actually wait for the condition to be notified the lock is released.
Or put the other way round: The reader only releases the lock while being blocked within CONDITION-WAIT. The writer can only notify while holding the lock.
=> CONDITION-NOTIFY can only be called when the reader is blocked in CONDITION-WAIT => no notifications get lost.
qed :)