首页 > 解决方案 > 是否可以在多个条件下使用 pthread 条件变量(pthread_mutex 和 pthread_cond_t)?

问题描述

我有一个多线程程序,每个线程都专注于自己的工作。当一个线程完成它的工作时,它会将事件驱动到主线程。

所以我想用pthread条件变量来实现这个想法(即pthread_cond_t和pthread_mutex_t)。数据结构将如下所示:

typedef struct peer_info {
    int ip; 
    int port;
    pthread_mutex_t peer_mutex;
    pthread_cond_t peer_cond;
    bool write_v;
    bool read_v;
    bool create_v;
    bool destroy_v;
} peer_info;

假设:
thread1改变write_v并向主线程发出信号,
thread2改变read_v并向主线程发出信号,
thread3改变create_v向主线程发出信号,
thread4改变destroy_v向主线程发出信号。

是否可以只使用一个 pthread_mutex 和 pthread_cond_t 来实现上述场景?会不会造成死锁?

标签: cpthreadsrace-condition

解决方案


是的,您可以放心地等待“复合谓词”,其中一个信号表示“此状态已更改该状态已更改某些其他状态已更改...”

在您的情况下,这些状态是event_v您设置的标志。假设您的主线程处于循环中,并且event_v标志已初始化为false,它看起来像这样:

// main loop:
pthread_mutex_lock(&pi.peer_mutex);
while (! (pi.write_v || pi.read_v || ... )) {
  pthread_cond_wait(&pi.peer_cond, &pi.peer_mutex);
}
if (pi.write_v) {
  pi.write_v = false; // clear this so we're not confused next time we wake up
  handle_write_event(&pi);
}
if (pi.read_v) {
  pi.read_v = false;
  handle_read_event(&pi);
}
if (...) ...          // handle other events

请注意,这将在互斥锁被锁定时处理事件,这对您来说可能合适,也可能不合适。

顺便说一句,我发现所有这些布尔标志有点麻烦,可能会使用位标志:

#define PEER_EVENT_READ  1 << 0
#define PEER_EVENT_WRITE 1 << 1
#define PEER_EVENT_ ...

struct peer_info {
  short events_pending; // initialized to zero
  ...
};

这样我就可以简洁地写:

while (! pi.events_pending) {
  pthread_cond_wait(&pi.peer_cond, &pi.peer_mutex);
}
if (pi.events_pending & PEER_EVENT_READ) { ... }
if ....
pi.events_pending = 0; // clear them all

但它在语义上是一样的,所以取决于你。


推荐阅读