1

after reading the c++ standards, I am still somewhat unclear as to what should happen when there are more then one thread blocked on a conditional and a third thread signals the condition.

From the spec:

The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond).

If more than one thread is blocked on a condition variable, the scheduling policy shall determine the order in which threads are unblocked.

Here it says at least one... but what does that really mean? - one and only one, or some undefined number of threads with a minimum of one?

I tested this with 3 threads (just showing the main loop): Note: This is pointless code, I am just using it to learn, and I know I can use pthread_cond_broadcast(), but I just want to fully understand pthread_cond_signal() first.

ticker thread: increments 'counter' and signals 'tickOccured' i.e. 'counter' has changed

while (1)
{
   // Get the mutex
   pthread_mutex_lock(&mutex);

   counter++;

   std::cout << "\t\t ticker: " << counter << std::endl;

   // Tell others that a tick has occured
   pthread_cond_signal(&tickOccured);

   // Release
   pthread_mutex_unlock(&mutex);

   sleep(1);
}

worker thread: checks the value of 'counter' and determines if thread3 should end by setting flag 'closeStarter'

while (1)
{
   // Get the mutex
   pthread_mutex_lock(&mutex);

   // Wait for a tick
   std::cout << "\t\t\t\t waiting..." << std::endl;
   pthread_cond_wait(&tickOccured, &mutex);

   std::cout << "\t\t\t\t worker: " << counter << std::endl;

   // Check if its time to end the starter
   if (counter >= TIME_FOR_STARTER_TO_EXIT)
   {
      // Set close starter flag
      closeStarter = true;
   }

   // Release
   pthread_mutex_unlock(&mutex);
}

starter thread: checks the flag 'closeStarter' and if its true exits

// Monitor things for a while and then exit when its time
while (!closeStarter)
{
   // Get the mutex
   pthread_mutex_lock(&mutex);

   std::cout << "Starter: waiting..." << std::endl;
   pthread_cond_wait(&tickOccured, &mutex);

   std::cout << "Starter: " << counter << std::endl;

   // Release
   pthread_mutex_unlock(&mutex);
}

std::cout << "Starter: Exiting..." << std::endl;
pthread_exit(NULL);

Result: What I observe is

Starter: Starting...
           ticker: Starting...
           ticker: 1
                     worker: Starting...
Starter: waiting...
                     worker: waiting...
           ticker: 2
Starter: 2
Starter: waiting...
           ticker: 3
                     worker: 3
                     worker: waiting...
           ticker: 4
Starter: 4
Starter: waiting...
           ticker: 5
                     worker: 5
                     worker: waiting...
           ticker: 6
Starter: 6
Starter: Exiting...
           ticker: 7
                     worker: 7
                     worker: waiting...
           ticker: 8
                     worker: 8
                     worker: waiting...
           ticker: 9
                     worker: 9
                     worker: waiting...

So when both starter and worker are waiting, only one or other get the signal, but never both. When starter exists, then worker always gets the signal. You would expect this behaviour as well if the spec read: one and only one thread will be unblocked, but it says at least one, so is there a case where more then one thread can be unblocked?

It's probably a fringe case I am talking about here, but I want to understand what this means. Example, if I wanted keep a queue of threads waiting for the same event, then I would need to ensure that only one receives the signal...

code_fodder
  • 15,263
  • 17
  • 90
  • 167
  • 1
    It is called *spurious wakeup*. Related question: http://stackoverflow.com/questions/8594591/why-does-pthread-cond-wait-have-spurious-wakeups – zch Sep 25 '14 at 12:07
  • 1
    When it says at least one, it literally means it. Your code should check for the corresponding data to assure something really happened. Furthermore, the waiting thread may be unblocked even when nothing happened. – Non-maskable Interrupt Sep 25 '14 at 12:10
  • Just a note, pthreads is not part of c++, it is a add on library. C++11 has a built in threading library (), including a condition variable that supports `notify_one` and `notify_all`, which are more precisely defined. – dohashi Sep 25 '14 at 13:09
  • @zch & Calvin: Thanks for the answers/comments. So by "at least one" it means one thread will unblock, but others may spuriously unblock (as is always the case).... makes sense now :) – code_fodder Sep 25 '14 at 13:12
  • Also, from the man page on my linux box: _pthread_cond_signal restarts one of the threads that are waiting on the condition variable cond. If no threads are waiting on cond, nothing happens. If several threads are waiting on cond, exactly one is restarted, but it is not specified which._ – dohashi Sep 25 '14 at 13:12
  • @dohashi I know that pthreads is not a explicit part of c++, I had to include it in the libraries... but I am not sure what you are trying to say :o I am using c++ and pthreads :) – code_fodder Sep 25 '14 at 13:14
  • Your first line says "after reading the c++ standards, I am still somewhat unclear..." pthreads is not part of the c++ standard. If your compiler supports I would strongly suggest using that instead. – dohashi Sep 25 '14 at 13:19
  • @dohashi Ah ok, yes that makes more sense now!, I was looking at the posix docs not c++ my mistake :) – code_fodder Sep 25 '14 at 13:22
  • 1
    It is unfortunate, but some OS upon which POSIX is hosted do have synchronization primitives that do not work in a sane manner. This means checking for the annoying 'spurious wakeups'. I've always considered this somewhat crazy - a bit like checking after a successful fopen() to ensure that the file is the right one and is actually open:) – Martin James Sep 26 '14 at 09:45

0 Answers0