1

编写生产者/消费者队列的最有效方法是什么,其中一个线程是生产者,另一个是消费者。在一篇论文中,作者说将一个元素插入他的队列需要一个原子操作,但他没有解释如何。

他的队列也是一个循环队列,如果队列为空,则消费者等待,而如果队列已满,则生产者等待。他怎么可能实现这样的队列。他所说的原子操作是指某种互斥体还是只是一个原子变量。注意他说,一个原子操作。

4

1 回答 1

1

如果您没有实现无锁队列的经验,唯一的答案可能是:最有效(和安全)的方法是使用锁,由 pthread(互斥锁或 cond var)提供。

无锁算法通常(但不一定)会给你一点额外的性能,但如果你不知道自己在做什么,它们可能会出错。

另一方面,Linux 下的 phtreads 实现尽可能避免锁定,并futex在需要时使用(同样,futex这是一种快速但您应该知道自己在做什么的地方)。
这样的队列每秒通过十万个任务没有问题。这可能看起来很有限,但实际上如果您需要每秒通过 1000 万个任务,那么您做错了。理想情况下,您可能每秒在队列上传递几十到一百个左右的任务(任务更少,但工作组更大)。例如,您想创建 50 个任务,每个任务处理半兆字节的数据,而不是 2500 万个任务处理一个字节的数据。

如果您仍然坚持尝试无锁实现(可能出于学术兴趣),您将需要一个原子比较交换操作(在 C 的 GCC 文档中查找“遗留 __sync 函数”,对于 C++,您将使用新的原子操作)。
请务必阅读诸如 ABA 之类的细微细节,为此您通常需要某种指针操作(将引用计数存储在最低 3 位中)或具有显式引用计数的双字交换。

或者,如果您做出一些假设,则可以仅使用原子添加或根本不使用任何原子操作来实现无锁队列(如果您只是出于好奇而感兴趣,请参阅“快进队列”)。然而,这些只有在假设成立的情况下才有效,而且它们更容易出错,所以最好远离它们。

于 2012-07-06T12:29:24.397 回答