如何确保 pthread_cond_wait() 不会遗漏任何 pthread_cond_signal()?

How to make sure pthread_cond_wait() doesn't miss any pthread_cond_signal()?

我有一个读取线程和多个写入线程,如下所示。

阅读线程:

pthread_mutex_lock(mutex);
while(1){
   pthread_cond_wait(cond, mutex);
   switch(state){
   //do something
   }
}
pthread_mutex_unlock(mutex);

写入线程 1:

pthread_mutex_lock(mutex);
state = work;
pthread_cond_signal(cond);
//do something
pthread_mutex_unlock(mutex);

写线程2:

pthread_mutex_lock(mutex);
state = lunch;
pthread_cond_signal(cond);
//do something
pthread_mutex_unlock(mutex);

假设 state 是共享变量,读取线程在所有写入线程之前进入等待状态。

假设两个写入线程同时尝试获取 mutex,而 write1 获取 mutex 并发送 cond。此时 write2 和 read 线程都锁定在 mutex 上,据我所知,没有线程优先于 mutex 所以我们不能确定 write1 什么时候释放mutex 读取线程将获取它,这将导致丢失信号和覆盖状态。

我这里有两个问题:

  1. 我的理解是否正确,上面的情况是可能的吗?
  2. 如果是这样,我如何确保我的代码中没有遗漏任何信号?
  1. Is my understanding correct, that the above situation is possible?

是的,你是对的。

  1. If so, how do I make sure that no signal is missed in my code.

如果要确保变量 state 的每次更改都被“读取线程”注意到,那么您必须确保没有“写入线程”更改变量 state直到它被“读线程”确认。例如,您可以让“读取线程”读取 state 的值,然后将该变量设置为一个特殊值,以向“写入线程”指示 state 现在可能被覆盖新值。

然而,这意味着不仅“读取线程”必须等待“写入线程”,而且“写入线程”也必须等待“读取线程”。这就是producer-consumer problem。一个典型的解决方案是有两个条件变量而不是一个:

  • 一个用于“写入线程”以向“reader 线程”指示新数据已准备好读取。
  • 一个用于“reader 线程”以指示“写入线程”现在可以写入新数据。

为了最大程度地减少线程之间的等待,您可能希望允许同时在程序中存储一组以上的数据,例如通过实现队列。

因为您不想错过任何状态更改,写入线程不应覆盖变量,而是将状态写入 FIFO(您可以将其实现为链表、管道或循环缓冲区 read/write 示例的指针)。然后,写入线程将推送状态(FIFO 中每个状态一个新元素),读取线程将一个一个弹出它们,直到 FIFO 为空(因为每次唤醒时 FIFO 中可能有多个状态) .

因此,您可以保留当前的信令实现,但只需更改 state 的管理方式:状态 FIFO 而不是单个变量。