【问题标题】:Why is `pthread_mutex_unlock` called before calling `pthread_cond_signal`?为什么在调用 `pthread_cond_signal` 之前会调用 `pthread_mutex_unlock`?
【发布时间】:2018-03-27 12:21:36
【问题描述】:

来自多处理器编程的艺术,

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_cond_signal之前先调用pthread_mutex_unlock

In Java, unlocking is called after calling signal. 那么为什么会有区别呢?

谢谢。

【问题讨论】:

标签: java concurrency synchronization pthreads monitor


【解决方案1】:

如果要在互斥锁解锁之前调用pthread_cond_signal,您会引入服务员(第一个示例中的“出队”)将立即唤醒并尝试在互斥锁解锁之前锁定互斥锁的可能性由信号线程解锁。因为您知道 dequeuer 需要做的第一件事就是锁定互斥锁,所以您几乎是在鼓励线程争用和由此产生的(不必要的)上下文切换。

在发出信号之前解锁互斥锁可以消除这种争用源。

【讨论】:

  • 谢谢。为什么Java中的顺序是颠倒的?
  • @Ben Java 中的顺序没有“颠倒”。你,程序员,决定你想在Java或pthreads中调用它们的顺序。安全的事情是在持有互斥锁时发出条件信号,如果你想在没有持有互斥锁的情况下调用它,你需要对你的代码进行彻底的分析,以避免在条件上丢失信号,或者编写你的逻辑让它这样做错过条件信号也没关系。
  • @nos:谢谢。在此处的 pthread 示例中,是否有一些保证可以避免在条件下丢失信号?请注意,pthread 和 Java 中的示例均来自同一本书:The Art of Multiprocessor Programming。
猜你喜欢
  • 2022-09-29
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
  • 1970-01-01
  • 2017-05-14
  • 2023-03-21
  • 1970-01-01
  • 2011-04-19
相关资源
最近更新 更多