11

The Linux Programming Interface book has a piece of code (producer/consumer) to show how condition variable works:

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

static int avail = 0;

while (TRUE) {
    s = pthread_mutex_lock(&mtx);

    while (avail == 0) {   /* Wait for something to consume */
       s = pthread_cond_wait(&cond, &mtx);
    }

    while (avail > 0) {   /* Consume all available units */ 
        avail--;
    }

    s = pthread_mutex_unlock(&mtx);
}

Why we use pthread_mutex_lock in while? why we don't use it in an if?

Majid Azimi
  • 5,575
  • 13
  • 64
  • 113

1 Answers1

13

Because pthread_cond_signal() is allowed to wake up more than one thread waiting on the condition variable. Therefore you must double-check the condition once you wake up, because some other thread might have woken up and changed it ahead of you.

If you know you have just one thread waiting, and you are sure nobody in the future will ever modify code elsewhere in the program to add another thread waiting, then you can use if. But you never know that for sure, so always use while.

[update]

As ninjalj points out in a comment, my answer is incomplete for failing to mention "spurious wakeups". For example, the POSIX standard makes it clear that if the waiting thread receives a signal (e.g. via kill()), pthread_cond_wait() can return 0 even if no other thread signaled the condition variable. The standard is ambiguous (in my view) as to whether the waiting thread can be woken up for no reason at all... But the bottom line is: Always use while, not if.

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • 6
    Additionally, there can be spurious wakeups, so always use `while`. – ninjalj Jun 01 '11 at 19:20
  • What do you mean by: spurious wakeups – Majid Azimi Jun 01 '11 at 19:24
  • 1
    @Majid Azimi the condition variable can be signalled for no apparent reason, not just because someone called pthread_cond_signal/broadcast – nos Jun 01 '11 at 21:07
  • A minimal implementation could even implement `pthread_cond_wait` as `return 0;` and let the caller spin... ;-) Of course this would be extremely ugly. – R.. GitHub STOP HELPING ICE Jun 01 '11 at 22:00
  • I thought multiple threads being woken by pthread_cond_signal was the _definition_ of "spurious wakeup". Can any of you cite chapter and verse of the POSIX spec that says pthread_cond_wait() can return even if _no_ thread signals the condition variable? – Nemo Jun 01 '11 at 22:56
  • You might be right that that's what posix says. Though at least historically that was not the case in thread implementation(see e.g. [here](https://groups.google.com/group/comp.programming.threads/msg/bb8299804652fdd7?hl=de) for more discussions ). Though - you wouldn't really care nor be able to determin if the spurious wakeup was due to someone calling pthread_cond_broadast or something else. – nos Jun 01 '11 at 23:44
  • One mistake in my "minimal implementation": it would at least need to unlock and relock the mutex to allow other threads the opportunity to obtain it. – R.. GitHub STOP HELPING ICE Jun 01 '11 at 23:48