C ++中的并发队列

时间:2010-09-19 17:28:00

标签: c++ multithreading pthreads

我正在尝试设计一个可以由多个读/写线程同时访问的队列。我更喜欢使用2个互斥量,每个用于读写。写入很简单,锁定写入互斥锁,附加数据,解锁并完成。

问题在于阅读。如果in队列中没有数据,我希望我的线程等到数据可用。一种显而易见的方法是获取读取互斥锁并在每N个时钟周期内保持轮询队列,但这显然不是最好的方法。这让我了解条件变量。有没有人有任何好的资源讨论使用条件变量(最好是基于pthreads)在C ++中阻塞队列实现?

具体来说,我看到以下问题:

  1. 一旦完成写入,编写器线程将执行pthread_cond_signal数据存在,但它是如何知道某些读者线程正在等待的?除非有pthread_cond_wait,否则调用pthread_cond_signal是非法的。
  2. 是否可以调用pthread_cond_broadcast而不是pthread_cond_signal?也许这可能会绕过pthread_cond_wait的问题。这似乎更符合逻辑,因为多个读者线程绝对是一个真正的可能性。
  3. 似乎必须使用相同的互斥锁来锁定读写器线程以使用条件变量。如果这是真的那么我们就有一个严重的问题。

5 个答案:

答案 0 :(得分:3)

我有一个使用http://danborn.net/code/中相同互斥锁的实现,但就像我之前提到的那样,因为它使用了一个条件变量,它也使用了1个互斥锁。

这是升级版本,再次使用单个互斥锁:http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html

答案 1 :(得分:2)

我认为你误解了一些东西 - 即使没有线程在等待那个条件,调用pthread_cond_signal也是完全合法的。

此外,在多线程编程的上下文中,将某些内容称为“读取”操作 通常意味着它不会改变共享资源的状态。如果通过“阅读” 你的意思是“从队列的头部删除一个项目”,这会改变状态 队列(换句话说,它也是一个“写”。)根据你的情况,用“消费者和制作者”而不是“读者和作者”来思考可能会更好。

单个互斥锁(以保证对队列的独占访问)和两个条件变量(“可用数据”,“可用空间”)应该足以满足您的需要。 (如果 队列可以动态增长,你不需要“可用空间可用”条件变量; 我只是提到完整性。)

如果您的阅读主题严格读者(也就是说,他们以任何方式修改共享队列数据结构,例如通过弹出一个项目队列),pthread_rwlock系列调用也可能是一个合适的解决方案。在这个范例中,有读锁(多个读取器可以同时保持,但强制写入器阻塞直到读取器完成),并写锁(这确保了持有写锁的线程的独占访问,阻止任何其他编写器读者。)

答案 2 :(得分:2)

this C++ threading blog post的示例12-3应该为您提供参考实现,但我认为您自己的危险接近成功。解决您的具体问题:

  1. 没有服务员时发出信号 非法。这是完全合法的,你可以利用这个事实。 (你在哪里读到这个,顺便说一句?)
  2. pthread_cond_broadcast导致一个主要问题:群大象充电,其中所有 n 线程都醒来并开始在缓存之间拉入内存,即使只有其中一个可能会取得进展。它会起作用,但效率不高。
  3. 您可以从任何地方发出信号,甚至可以从一个永远不必处理相关互斥锁的线程发出信号。您的pthread_cond_wait来电必须释放读取互斥锁;这是唯一的要求,而且这是唯一需要与条件变量交互的互斥锁。
  4. 从#3开始,你的想法存在一个主要问题:作者线程必须锁定两者读取和写入互斥锁。如果没有,会发生什么当队列大小为1并且你有一个读者和一个作家同时行动时?

答案 3 :(得分:1)

您是否考虑过使用信号量而不是条件变量?信号量是等待的,即使没有线程在等待,也可以表示“队列非空”状态。

答案 4 :(得分:0)

一个简单的boost :: condition示例位于here