Skip to content
Advertisement

How does pthread_cond_wait (conditon variable) unblock all threads only once, not multiple times?

I have successfully implemented a producer thread and 2 worker threads or consumer threads.

The producer thread broadcasts condition using pthread_cond_broadcast. And the worker threads are blocked by pthread_cond_wait.

The code looks something likes this:

Thread 1 (Producer Thread):

pthread_mutex_lock
pthread_cond_broadcast
pthread_mutex_unlock

Thread 2 (Worker/Consumer Thread):

work = 1
while(1)
{
  pthread_mutex_lock
  while(!work)
  {
    work = 1;
    pthread_cond_wait
  }

  // Thread operation
  work = 0;
  pthread_mutex_unlock
}

Thread 3 (Worker/Consumer Thread):

work = 1
while(1)
{
  pthread_mutex_lock
  while(!work)
  {
    work = 1;
    pthread_cond_wait
  }

  // Thread operation
  work = 0;
  pthread_mutex_unlock
}

My question is why does Thread 2 or Thread 3 does not re-execute itself ?

In other words, when the condition was broadcasted by Thread 1, lets say Thread 2 unblocks on the condition first, performs thread operation and calls thread_cond_wait and blocks itself.

Now Thread 3 unblocks on the condition, performs thread operation and calls thread_cond_wait and block itself.

At this point of time, both the threads are blocked waiting for the condition, so is the condition variable reset ? If so, how does it know when to reset, as instead of 2 worker threads, I could have 5 worker threads ?

Why doesn’t Thread 2 and Thread 3 unblock themselves again for the same condition ?

I wanted to know the internal mechanism, about how the threads unblock for a particular condition only once, not again, until a new broadcast is sent.

I have tried to read about this, but all I could see was, if a condition broadcast is sent, all threads waiting for that condition are unblocked. What I don’t understand is why does the same thread not unblock for the same condition multiple times ?

I have tried looking at the pthread_cond_t, but could not get any clue.

Any help or suggestion about what I am lacking or thinking wrong, will be appreciated.

Thanks

Advertisement

Answer

My question is why does Thread 2 or Thread 3 does not re-execute itself ?

Because that’s not how condition variables work.

In other words, when the condition was broadcasted by Thread 1, lets say Thread 2 unblocks on the condition first, performs thread operation and calls thread_cond_wait and blocks itself.

Now Thread 3 unblocks on the condition, performs thread operation and calls thread_cond_wait and block itself.

At this point of time, both the threads are blocked waiting for the condition, so is the condition variable reset ?

That question suggests a poor model of the state represented by a condition variable, for the answer is both yes and no. Implementation details can vary widely, but notionally, the primary state managed by a CV consists of a “wait set” of threads currently waiting on the CV. Those threads cannot proceed, i.e. they are blocked on the CV.

There are three main operations that can be performed on a CV:

  • A thread can add itself to a CV’s wait set by performing a “wait” operation on it, thus causing itself to block on the CV.
  • A thread can cause a single other thread, chosen by the CV, to be removed from a CV’s wait set (if nonempty) by performing a “notify” operation on it. Both threads are then eligible to proceed as far as the CV is concerned.
  • A thread can cause a CV’s wait set to be emptied by performing a “broadcast” operation on it.

CVs do not carry persistent state indicating whether they have been signaled. They just know their wait sets and (in pthreads’ implementation) a mutex that threads that have been removed from the wait set must acquire before they can return from a wait operation. There is no need to reset a CV to prepare it to accept more threads into its wait set.

If so, how does it know when to reset, as instead of 2 worker threads, I could have 5 worker threads ?

It doesn’t reset, not in any sense that is distinct from the operations already described. Any thread that waits on it gets added to the wait set, and is ineligible to be scheduled as long as it remains there. Any signal and broadcast operations on the CV affect the wait set as of the time the operation is performed, atomically. Threads removed from the wait set are no longer blocked on the CV, but they may instead be blocked on acquiring the associated mutex.

Why doesn’t Thread 2 and Thread 3 unblock themselves again for the same condition ?

Because that’s not how condition variables work.

Threads 2 and 3 waiting again is the only kind of resetting that CVs support. Those threads having been readded to the wait set, there is no reason to think that they would proceed before a(nother) signal or broadcast operation is performed on that CV. There is no memory of past signals / broadcasts, only the current contents of the wait set.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement