多消费者的无锁队列的实现



最近我遇到了这个问题:有3个消费者线程,需要实现 lock free queue(不能使用同步(,以免不会阻止使用的线程。假设队列已经包含数据。

我考虑了一段时间,并遇到了 atomic 操作,如果仔细使用,可以帮助您。我的实现如下所示。由于数据已经存在于队列中,因此我尚未实现enqueue方法并填充构造函数内的数组。

public class SPMCQueue {
    private AtomicInteger index = new AtomicInteger(0);
    public int[] arr;
    public SPMCQueue(int size) {
        arr = IntStream.range(0, size).toArray();
    }
    public Integer dequeue() {
        Integer ret = null;
        int x = index.getAndIncrement();
        if (x < arr.length) {
            ret = arr[x];
            System.out.println(arr[x] + " by " + Thread.currentThread().getName());
        }
        else {
            throw new RuntimeException("Queue is empty");
        }
        return ret;
    }
}
class QueueTest {
    public static void main(String[] args) {
        SPMCQueueq = new SPMCQueue(40);
        Runnable t1 = () -> {
            try {
            while (true) {
                q.dequeue();
            }
            }catch(Exception e) {
            }
        };
        Runnable t2 = () -> { 
            try {
            while(true) { q.dequeue(); }
            }catch(Exception e) {
            }
        };
        Runnable r3 = () -> { 
            try {
                while(true) { q.dequeue(); }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                //e.printStackTrace();
            }
        };
        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);
        Thread thread3 = new Thread(r3);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

我已经执行了上述程序,结果表明,所有3个消费者都在消耗数据,尽管订单过时,并且某些线程比其他线程所消耗的数据更多,但是我看不出任何数据出现多次在O/p中。

我有以下问题:

  1. 上述实施中是否有任何问题?

  2. 实施无锁的消费者队列的其他方法是什么?

我想与答案同时回复:https://stackoverflow.com/a/21101904/7340499,因为这与您的问题类似。

所以,您的问题:

,但我看不到任何数据出现在O/p。

这是预期的。因为,getAndIncrement((是原子质,任何时候访问该功能时,您将获得不同的x值,因此会获得不同的输出。但是,由于将" getAndIncrement(("one_answers" system.out.print(("在单个非原子dequeue操作中起作用,因此您的输出有时可能会过失,例如您可以在一个线程上获得x = 1,另一个线程中断,获取x = 2并打印它,然后您的初始线程最终确定打印。我相信这也指出了您实施的问题,如(1(中所述。您的应用程序可以通过排序处理的队列处理吗?

实施无锁的消费者队列的其他方法是什么?

好吧,正如您已经注意到的那样,原子操作是一种方法。但是从本质上讲,它们都非常像锁。他们只是在较小的规模上运行(不过,有一些实现差异(。因此,至少对于我自己,很难将它们概念化为不同的方法。除此之外,我相信这里还有一些不错的资源:锁定队列 - 单个生产商,多个消费者

最新更新