2017-10-16 45 views
0

从多处理器编程的艺术,为什么在调用`pthread_cond_signal`前调用`pthread_mutex_unlock`?

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 } 

和高级编程在Unix环境

void 
enqueue_msg(struct msg *mp) 
{ 

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

} 

为什么pthread_mutex_unlock调用pthread_cond_signal之前叫什么名字?

In Java, unlocking is called after calling signal. 那么,为什么不同?

谢谢。

+0

我认为这是错误的。看看https://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex –

+0

@JerryJeremiah谢谢。在APUE中,有一个例子在发送信号之前也释放锁定。查看我的更新。 – Ben

回答

1

如果pthread_cond_signal将被称为被解锁的互斥体之前,你介绍的可能性,即一个服务员(一个在第一个例子“dequeuer”)会立即清醒和尝试互斥之前锁定互斥被解锁信号线程。因为你知道出列者需要做的第一件事是锁定互斥锁,所以你几乎鼓励了线程争用以及由此产生的(不必要的)上下文切换。

在信令之前解锁互斥消除了争用的来源。

+0

谢谢。为什么订单在Java中颠倒了? – Ben

+0

@Ben在java中的顺序不是“逆转”。你,程序员,用Java或pthreads决定你想要调用哪些命令。安全的事情是当互斥信号被保持时发出信号,如果你想在没有互斥信号的情况下调用它,你需要彻底地分析你的代码,以避免丢失信号,或者编写你的逻辑无论条件信号是否被漏掉都没关系。 – nos

+0

@nos:谢谢。在这里pthread的例子中,是否有一些保证可以避免条件上的丢失信号?请注意,pthread和Java中的例子都来自同一本书:多处理器编程的艺术。 – Ben

相关问题