You asked me to elaborate.
There are two discussions we had about this example.
First, in the code (page 29) there are already multiple conditions that are signaled in an arbitrary order – the left and right signals for a given philosopher. Those are both signaled when a philosopher thinks, and when the first one is signaled it will likely wake a waiting thread before the second one is signaled. So a given waiting philosopher would see his left and rights get signaled left-first or right-first at different times. Since you cannot wait on multiple Condition objects at the same time, the lower-case c conditions need to be checked each time the thread begins to run again. To get at this, perhaps the self-study question could ask why the loop is necessary and what would happen if the
while loop was removed and just replaced with an
The second discussion we had (although not as relevant to this example) was that if someone uses a
signalAll() instead of a
signal(), all threads will wake up. However, just because they are eventually able to grab the lock, that does not mean the condition they were waiting on is now true. This would be a case where one could have a single lower-case c condition and upper-case c Condition but where you still need the loop. This is probably difficult to connect to the philosopher question but might be worth putting into the self-study as well.