A condvar is not a semaphore …

I’ve been running into some situations lately where developers have been using condition variables (the pthread_cond_* family of functions) as semaphores (the sem_* family of functions) … but instead introducing bugs into their programs.The confusion is somewhat understandable. Given that condition variables have a wait() and a signal() function similar to the wait() and post()  function available for semaphores, the two might seem interchangeable.Here is an example of a condvar being used improperly as a semaphore replacement:

 struct _data { 
  pthread_mutex_t m; 
  pthread_condvar_t c; 
  ... other stuff ... 
 }; 
void * writer_thread(void *arg) { 
  struct _data *d = (struct _data *)arg; 
  ... 
  pthread_mutex_lock(&d->m); 
  pthread_cond_signal(&d->c); 
  pthread_mutex_unlock(&d->m); 
  ... 
 } 
void * reader_thread(void *arg) { 
  struct _data *d = (struct _data *)arg; 
  ... 
  pthread_mutex_lock(&d->m); 
  pthread_cond_wait(&d->c, &d->m); 
  pthread_mutex_unlock(&d->m); 
  ... 
 }

The _intention_ here is that the writer_thread is signaling to the reader_thread that things are good and it can continue to operate. If this code were using sem_post()/sem_wait() the code would like operate as intended (assuming proper initialization values).However, imagine the following execution sequence (cause by context switches):

writer_thread:pthread_mutex_lock() 
reader_thread:pthread_mutex_lock() > blocks (mutex held) 
writer_thread:pthread_cond_signal() 
writer_thread:pthread_mutex_unlock() 
reader_thread:pthread_cond_wait() > blocks waiting 
...

In this case the writer thread had signaled the reader thread, but since the reader thread was not yet blocked, that signalling is lost. In the best case the writer_thread will have to wait a few extra cycles until the next reader_thread update or in the worst case the writer_thread may block forever if there are no further updates.

Condition variables are like semaphores on steroids. You can trigger off of much more sophisticated combinations of data, but at the cost of managing those triggers and that data yourself.

Assuming that we want our example to respond to every written request, and behave like a counting semaphore, then we should modify it as follows:

struct _data { 
  pthread_mutex_t m; 
  pthread_condvar_t c; 
  int data; 
  ... other stuff ... 
};  

void * writer_thread(void *arg) { 
  struct _data *d = (struct _data *)arg; 
  ... 
  pthread_mutex_lock(&d->m); 
  d->data++; 
  pthread_cond_signal(&d->c); 
  pthread_mutex_unlock(&d->m); 
   ... 
}  

void * reader_thread(void *arg) { 
  struct _data *d = (struct _data *)arg; 
  ... 
  pthread_mutex_lock(&d->m); 
   while(d->data <= 0) { 
  pthread_cond_wait(&d->c, &d->m); 
  } 
  d->data--; 
  pthread_mutex_unlock(&d->m); 
  ... 
 }

As you can see, the state data management is more manual, but is entirely within your control. In this case we are triggering on every data increment, but it can be easily adjusted to trigger on every fifth data increment instead.

void * reader_thread(void *arg) { 
  ... 
  while(d->data <= 5) { 
  pthread_cond_wait(&d->c, &d->m); 
  } 
  d->data -= 5; 
  ...

Code that uses a condvar in a lock/wait/unlock scenario without any intermediate condition testing being done around the wait should always be viewed with suspicion since chances are it was once a semaphore implementation that was switched to using condvars.

 If you wanted to give this code a bit of an additional performance boost, you could also avoid the (little) thundering herd problem that is introduced here by moving the condvar signalling operation of the writer thread to occur outside of the mutex locked area.  This will save the reader thread from waking up from the condition variable, only to go mutex blocked until the mutex is given up.

6 comments so far

  1. [...] flexibility and potentially higher throughput. If that is the case, reading through the post a condvar is not a semaphore might be usefull. *Named semaphores, normal semaphores and mutexes can all be used as [...]

  2. Ну и почему это только так? Я считаю, почему не расширить данную тему.

  3. Объясните почему только так? Сомневаюсь, как можно прояснить этот обзор.

  4. Prnewswire.Com on

    I have experimented with pretty much every type of e-cig on the market.

    I will honestly tell you just how Green Smoke cigarettes is the best
    one! I use to sell e-cigs, and after dealing with a ton
    of issues, I realized I was selling junk. Green Smoke cigarettes has done their homework.
    No leaks, absolutely no dead power packs and atomizers.
    Plus, the batteries last forever between fees. I love Green Smoke a great deal, I sold-out my business and have become a sales person.
    for them. It really is Green Smoke cigarettes for me completely!

  5. web site on

    Permanent installations in vehicles gave way to
    the portable Bag Phones, designed with a cigarette lighter plug.

    According to Alexandra Juhasz, professor of media studies at California’s
    Pitzer College then one of the course facilitators, approximately 300 students have subscribed to the course, which falls
    underneath the Fem – Tech – Net rubric ‘Dialogues on Feminism and Technology.
    * Create and distribute Widgets or Mash-ups using services
    like widgetbox, Open Social, or Yahoo Pipes.

  6. www.youtube.com on

    It is not always about following a recipe letter for letter.
    These include an ice cream maker, juicer, slicer, strainer, and ravioli maker.
    Kitchen – Aid Assortment Hoods have types for the purpose of the island or peninsula owners, and also
    these variations are incredibly inspirational.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: