【问题标题】:How can I implement a single-writer, multiple-reader queue with pthreads?如何使用 pthread 实现单写入器、多读取器队列?
【发布时间】:2019-09-16 05:57:33
【问题描述】:

我正在尝试在 pthreads 中实现单写入器、多读取器队列。同步模式有效,但在重复请求后最终死锁(我相信)。它无限期地与一个作家老板线程和一个读者工作线程一起工作,但如果我有一个作家老板线程和多个阅读工作线程,它最终会挂起。当我在 gdb 中回溯时,我看到了这个:

// Boss:
Thread 1 (Thread 0x7ffff7fd1780 (LWP 21029)):
#0  0x00007ffff7bc44b0 in futex_wait
...

// Worker:
Thread 2 (Thread 0x7ffff42ff700 (LWP 21033)):
#0  0x00007ffff7bc39f3 in futex_wait_cancelable 
...

// Worker:
Thread 3 (Thread 0x7ffff3afe700 (LWP 21034)):
#0  0x00007ffff7bc39f3 in futex_wait_cancelable
...

对我来说,这似乎是工人们在等待信号,而老板则在等待信号而不发送信号。但是,我不知道为什么会这样。

我已经尝试过这种同步模式:

// Boss:
pthread_mutex_lock(&queue_mutex);
queue_push(&queue, data);
pthread_cond_signal(&queue_condition);
pthread_mutex_unlock(&queue_mutex);
return;

// Worker(s):
pthread_mutex_lock(&queue_mutex);
while((queue_isempty(&queue)) > 0) { 
    pthread_cond_wait(&queue_condition, &queue_mutex);
}
data_t *data = queue_pop(&queue);
pthread_mutex_unlock(&queue_mutex);
do_work(data);

据我所知,这是正确的同步模式。但是,有证据表明我没有应用正确的模式。有人可以帮我理解为什么 pthreads 中的这种单写入器、多读取器队列访问无法按我的预期工作吗?

【问题讨论】:

  • 发布的代码对我来说看起来是正确的。问题似乎出在您未发布的某些代码中。您能否发布一个完整的代码示例,以便我们重现问题。
  • 顺便说一句:此类问题的指南说:“寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误 和在问题本身中重现它所需的最短代码
  • 是的,我同意这段代码看起来是正确的。您还应该显示更多的回溯 - 它应该识别代码中的哪些行死锁(看起来其他线程必须持有queue_mutex,阻止生产者线程获取它)。
  • “真实*”代码是否也完全错过了错误检查?

标签: c multithreading pthreads thread-synchronization


【解决方案1】:

这里是基于可用代码-let 的最佳猜测。死锁可能是由于worker在等待信号时持有锁,而boss没有机会持有锁(当worker持有它时,为了发送信号)。以下应该避免死锁。

// Boss:
pthread_mutex_lock(&queue_mutex);
queue_push(&queue, data);
pthread_mutex_unlock(&queue_mutex);
pthread_cond_signal(&queue_condition);
return;

// Worker(s):
while((queue_isempty(&queue)) > 0) {   //> assume queue_isempty(const void*);
    pthread_cond_wait(&queue_condition, &queue_mutex);
}
pthread_mutex_lock(&queue_mutex);
data_t *data = queue_pop(&queue);
pthread_mutex_unlock(&queue_mutex);
do_work(data);

【讨论】:

  • 1.: 这个while((queue_isempty(&queue)) 可以同时访问queue 并且不受保护。不好。 2.:pthread_cond_wait() 返回queue_mutex 的时刻按定义锁定。无需再次锁定。
  • @alk 这两个是相关的——在这个答案中,pthread_mutex_lock(&queue_mutex); 行被错误地移到了while() 循环之后——并且对pthread_cond_signal(&queue_condition); 的调用同样被移到使用 mutext 完成没有被锁定。
  • @AndrewHenle:“知道这一个的举动没有意义,但它仍然引入了两个错误,正如我的评论中提到的那样。
  • pthread_cond_wait() 在等待时释放互斥锁(线程必须在调用函数时将其锁定)。
猜你喜欢
  • 2011-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 2017-02-09
  • 1970-01-01
  • 2018-06-08
  • 1970-01-01
相关资源
最近更新 更多