4

OK. The example here is provided using pthread lib in c.

In textbook I came across the following code:

//for thread 2
pthread_mutex_lock(&lock);
should_wake_up = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);

This code works out pretty fine. I just wonder will the following code also works?

//for thread 2
pthread_mutex_lock(&lock);
should_wake_up = 1;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond);//signal the conditional variable but the lock is not held

What's the pros and cons for the following code?

PS. Suppose the cooperating thread has the code:

//for thread 1
pthread_mutex_lock(&lock);
while(!should_wake_up)
    pthread_cond_wait(&cond, &lock);
pthead_mutex_unlock(&lock);

PS2. I came across some other question, which points out that if we don't want signal being lost, we must use lock to make sure that the associated predicate (in this case, is should_wake_up) can not be changed when the lock is held in thread 1. In this case, this seems not to be the issue. Link to the post: [1]: signal on condition variable without holding lock. I think his issue is that he forget about locking. But my question is different.

Han XIAO
  • 1,148
  • 9
  • 20
  • 1
    Every time this question is asked, a vicious debate ensues between those who correctly interpret the issue, and those who fundamentally misunderstand it. You need to have a shared predicate between the `*_wait()`-ing task and the `*_signal()`-ing task, and this state must be protected by a mutex, because it is accessed concurrently from multiple threads. The condvar itself must also be protected by a mutex. The mutexes (mutices?) must be the same. Consequently, the `signal()`-er must have **aqcuired** the mutex before modifying the shared state. It does not have to **hold** the lock anymore. – EOF Mar 01 '20 at 18:57

1 Answers1

7

For normal usage, you can unlock the mutex before signalling a condition variable.

The mutex protects the shared state (in this case the should_wake_up flag). Provided the mutex is locked when modifying the shared state, and when checking the shared state, pthread_cond_signal can be called without the mutex locked and everything will work as expected.

Under most circumstances, I would recommend calling pthread_cond_signal after calling pthread_mutex_unlock as a slight performance improvement. If you call pthread_cond_signal before pthread_mutex_unlock then the waiting thread can be woken by the signal before the mutex is unlocked, so the waiting thread then has to go back to sleep, as it blocks on the mutex that is still held by the signalling thread.

Anthony Williams
  • 66,628
  • 14
  • 133
  • 155