Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POSIX Threads: Condition Variables - what's the point?

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?

like image 524
Matthew Iselin Avatar asked Nov 27 '22 10:11

Matthew Iselin


2 Answers

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 allow one thread to notify some other thread that some event has occurred.

like image 174
1800 INFORMATION Avatar answered Dec 09 '22 09:12

1800 INFORMATION


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.

like image 38
Logan Capaldo Avatar answered Dec 09 '22 09:12

Logan Capaldo