views:

666

answers:

3

Hi everyone.

I've been working with pthreads a fair bit recently and there's one little thing I still don't quite get. I know that condition variables are designed to wait for a specific condition to come true (or be 'signalled'). My question is, how does this differ at all from normal mutexes?

From what I understand, aren't condition variables just a mutex with additional logic to unlock another mutex (and lock it again) when the condition becomes true?

Psuedocode example:

mutex mymutex;
condvar mycond;
int somevalue = 0;

onethread()
{
    lock(mymutex);

    while(somevalue == 0)
        cond_wait(mycond, mymutex);

    if(somevalue == 0xdeadbeef)
        some_func()

    unlock(mymutex);
}

otherthread()
{
    lock(mymutex);

    somevalue = 0xdeadbeef;

    cond_signal(mycond);

    unlock(mymutex);
}

So cond_wait in this example unlocks mymutex, and then waits for mycond to be signalled.

If this is so, aren't condition variables just mutexes with extra magic? Or do I have a misunderstanding of the fundamental basics of mutexes and condition variables?

+3  A: 

The two structures are quite different. A mutex is meant to provide serialised access to a resource of some kind. A condition variable is meant to all one thread to notify some other thread that some event has occurred.

1800 INFORMATION
Mutexes providing serialised access is what I seem to have been missing in my knowledge. Thanks.
Matthew Iselin
+1 for good solid definitions.
Platinum Azure
+4  A: 

They aren't exactly mutexes with extra magic, although in some abstractions (monitor as used in java and C#) the condition variable and the mutex are combined into a single unit. The purpose of condition variables is to avoid busing waiting/polling and to hint to the run time which thread(s) should be scheduled "next". Consider how you would write this example without condition variables.

while(1) {
  lock(mymutex)
  if( somevalue != 0)
     break;
  unlock(mymutex);
}

if( somevalue == 0xdeadbeef )
  myfunc();

You'll be sitting in a tight loop in this thread, burning up a lot of cpu, and making for a lot of lock contention. If locking/unlocking a mutex is cheap enough, you may be in a situation where otherthread never even has a chance to obtain the lock (although real world mutexes generally distinguish between the owning thread and having the lock, as well as having notions of fairness so this is unlikely to happen in reality).

You could reduce the busy waiting by sticking a sleep in,

while(1) {
  lock(mymutex)
  if( somevalue != 0)
     break;
  unlock(mymutex);
  sleep(1); // let some other thread do work
}

but how long is a good time to sleep for? You'll basically just be guessing. The run time also can't tell why you are sleeping, or what you are waiting on. A condition variable lets the run time be at least somewhat aware of what threads are interested in the same event currently.

Logan Capaldo
Thanks - that definitely explains the *why* really well.
Matthew Iselin
+2  A: 

The simple answer is that you might want to wake more than one thread from the condition variables, but mutex allows only one thread execute the guarded block.

leiz
That's a logical way of looking at it. Thanks!
Matthew Iselin
You might have more than one condition that the waiting thread is interested in. It might act if one condition is met, or if all are met. Or you might have multiple threads waiting on conditions. What's important to realize is that the waiting thread awakens not when the condition is true, but when there is a signal that something happened that might change one or more conditions that the condition variable protects.It is true that one can implement condition variables with mutexes and semaphores, but it is tricky. Every implementation that I've seen is unnecessarily convoluted.
Jive Dadson