Why is `pthread_mutex_unlock` called before callin

2019-08-17 06:47发布

问题:

From The Art of Multiprocessor Programming,

1 #include <pthread.h>
2 #define QSIZE 16
3 typedef struct {
4     int buf[QSIZE];
5     long head, tail;
6     pthread_mutex_t *mutex;
7     pthread_cond_t *notFull, *notEmpty;
8 } queue;
9 void queue_enq(queue* q, int item) {
10     // lock object
11     pthread_mutex_lock (q->mutex);
12     // wait while full
13     while (q->tail - q->head == QSIZE) {
14         pthread_cond_wait (q->notFull, q->mutex);
15     }
16     q->buf[q->tail % QSIZE] = item;
17     q->tail++;
18     // release lock
19     pthread_mutex_unlock (q->mutex);
20     // inform waiting dequeuers
21     pthread_cond_signal (q->notEmpty);
22 }

and from Advanced Programming in Unix Environment

void
enqueue_msg(struct msg *mp)
{

    pthread_mutex_lock(&qlock);
    mp->m_next = workq;
    workq = mp;
    pthread_mutex_unlock(&qlock);
    pthread_cond_signal(&qready);

}

Why is pthread_mutex_unlock called before calling pthread_cond_signal?

In Java, unlocking is called after calling signal. So why is the difference?

Thanks.

回答1:

If pthread_cond_signal were to be called before the mutex was unlocked, you introduce the possibility that a waiter (a 'dequeuer' in the first example) will immediately awake and attempt to lock the mutex before the mutex is unlocked by the signaling thread. Because you know the first thing the dequeuer is going to need to do is lock the mutex, you're almost encouraging thread contention and the resultant (unnecessary) context switching.

Unlocking the mutex before signaling eliminates this source of contention.