是否存在多个读取或写入线程的无锁队列?

时间:2010-06-11 06:28:57

标签: multithreading queue lockless

我在想,当多个线程正在读取或写入时,是否有可能拥有无锁队列?我已经看到了一个带有无锁队列的实现,它可以使用一个读取线程和一个写入线程,但对于任何一个都不会超过一个。可能吗?我认为不是。可以/有没有人想证明它?

6 个答案:

答案 0 :(得分:14)

有多种算法可用,我最终实现了An Optimistic Approach to Lock-Free FIFO Queues,它通过指针标记避免了ABA问题(需要CMPXCHG8B上的x86指令),它运行正常在生产应用程序中(用Delphi编写)。 (Another version, with Java code

然而,要真正无锁,你还需要一个无锁内存分配器 - 请参阅Scalable Lock-Free Dynamic Memory Allocation(在Concurrent Building Block中实现)或NBMalloc(但到目前为止,我没有使用其中一种)。

您可能还想查看optimistic lock-free FIFO queues impl?

的答案

答案 1 :(得分:3)

Java的无锁队列实现允许读写。这项工作是通过比较和设置操作(这是一个单CPU指令)完成的。

ConcurrentLinkedQueue使用一种方法,在这种方法中,线程可以帮助彼此从队列中读取(或轮询)对象。由于它是链接的,队列的头部可以接受写入,而队列的尾部可以接受读取(假设有足够的空间)。所有这些都可以并行完成,完全是线程安全的。

答案 2 :(得分:1)

使用.NET 4.0,有ConcurrentQueue(T) Class 简而言之,根据C#4.0,这是一个无锁实现。另请参阅此blog entry

答案 3 :(得分:0)

您并不特别需要锁定,而是从队列中删除内容的原子方法。没有锁定和原子test-and-set指令也可以这样做。

答案 4 :(得分:0)

Primoz Gabrijelcic(Delphi Geek)在OmniThreadLibrary中有一个动态锁定免费队列:http://www.thedelphigeek.com/2010/02/omnithreadlibrary-105.html

答案 5 :(得分:0)

使用.NET 4.0,有ConcurrentQueue Class

样品

https://dotnetfiddle.net/ehLZCm

public static void Main()
{
    PopulateQueueParallel(new ConcurrentQueue<string>(), 500);
}

static void PopulateQueueParallel(ConcurrentQueue<string> queue, int queueSize)
{
    Parallel.For(0, queueSize, (i) => queue.Enqueue(string.Format("my message {0}", i)));
    Parallel.For(0, queueSize,
        (i) =>
        {
            string message;
            bool success = queue.TryDequeue(out message);
            if (!success)
                throw new Exception("Error!");

            Console.WriteLine(message);
        });
}