5

I have been carefully studying the accepted answer to the following SO question: C++0x has no semaphores? How to synchronize threads?

In the semaphore implementation in that answer, here is the implementation of the wait() function:

void wait()
{
    boost::mutex::scoped_lock lock(mutex_);
    while(!count_)
        condition_.wait(lock);
    --count_;
}

I am trying to understand the purpose of the while(!count_) condition.

The answer to another SO question ( How does this implementation of semaphore work? ) indicates that when notify_one() is called on the condition variable, that it is possible that MORE THAN ONE thread waiting on that condition variable will be woken up - hence the need for the while loop. I would like to have this confirmed - is that the full and/or correct answer, or are there other reasons why the while loop is necessary?

If more than one thread wakes up, which thread owns the mutex? The more I think about it, the more ill-defined it seems to be if more than one thread can wake up due to a single call to notify_one(). Would it not be possible for BOTH woken-up threads to see the count_ value as higher than 0, and proceed to both decrement count_, resulting in a count_ value of less than 0, and defeating the purpose (and correctness) of the semaphore?

Community
  • 1
  • 1
Dan Nissenbaum
  • 13,558
  • 21
  • 105
  • 181

1 Answers1

3

There could be spurious wakeups, or notify_one could wake up more than one thread due to implementation details, as you've already mentioned.

Waking up multiple threads doesn't mean though that all of them can enter the protected section at the same time, it just means that when ThreadA releases the lock, ThreadB (which got woken up along with ThreadA in the previous example) also gets to enter the protected section. By this time ThreadA has already done its work, so ThreadB won't see the count variable in the same state as ThreadA found it.

mitchnull
  • 6,161
  • 2
  • 31
  • 23