编写单个生产者/单个使用者队列的最有效方法

时间:2012-07-06 12:12:40

标签: c linux gcc x86-64

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

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

1 个答案:

答案 0 :(得分:1)

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

无锁算法通常(但不一定)会给你一些额外的性能,但如果你不确切知道自己在做什么,它们就会非常错误。

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

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

或者,无锁队列只能使用原子添加或根本没有任何原子操作来实现(如果你只是为了好奇,请参阅“快进队列”),如果你做了一些假设。然而,这些只有在假设成立时才有效,并且它们更容易出错,所以最好远离它们。