在C \ C ++中实现多生产者/消费者无锁队列

时间:2011-12-03 22:27:49

标签: c++ multithreading queue nonblocking

我已经在无锁队列上的单个生产者/消费者上完成了我的基本实现,并且运行良好。但是,当我尝试将其扩展到多个生产者/消费者时,我开始遇到冲突。我通过SO找到了与此问题相关的类似帖子(Is there such a thing as a lockless queue for multiple read or write threads?),我发现了一篇文章,对原始实现进行了进一步的介绍。我也对这篇希望得到一些指导的文章感到困惑。

第一个是这个实现在使用多个生产者/消费者时真的有用吗?或者在原始的Michael-Scott实现中缺少某些与多个生产者/消费者设置一起工作的东西。

第二个是文章An Optimistic Approach to Lock-Free FIFO Queues,Dequeue部分显示了虚拟值的使用。如何确定要使用的适当值?如果我使用整数,那么我会确定我为虚拟值选择的整数不是我决定排队的实际值吗?

任何建议或总体方向都会很棒。如果有人想知道我在Visual Studio中创建它以更好地理解非阻塞算法。我想尽可能地使它成为通用的,这样我就可以排队所需的任何内容(队列中的数据是模板化的,因此用户可以指定要排队的内容)。

3 个答案:

答案 0 :(得分:5)

谨防邪恶:ABA problem

您可以开始阅读thisthisthis

答案 1 :(得分:0)

您可以制作便宜的包装类型,以便您可以跟踪项目的有效性,并且用户可以透明地传递值而不必担心它。这会产生一些小的内存开销,但是如果你想允许空值的入队和出列(而不是将它们视为“虚拟”标记),那么实际上并没有更好的方法。

示例:

template<typename T>
class MyQueue
{
    /* . . . */
public:
    void Enqueue(T * value)
    {
        MyQueueItem item;
        item.value = value;
        item.isValid = true;

        /* enqueue it now
           . . . */
    }

    T * Dequeue()
    {
        MyQueueItem validItem;
        /* Get the first element where isValid == true
           . . . */
        return validItem.value;
    }

private:
    struct MyQueueItem
    {
        T * value;
        bool isValid;
    };
};

答案 2 :(得分:0)

没有明确支持在C ++中实现非阻塞队列所需的原子cpu指令(但是,它在更新的规范中)。

可以访问您机器上的说明,但您必须内联某个程序集或找到为您执行此操作的库(TBB或升级版)。