【发布时间】:2019-04-30 21:04:51
【问题描述】:
最近我遇到了这个问题:据说有3个消费者线程,需要实现一个无锁队列(不能使用同步),这样就没有消费了线程被阻塞。假设队列已经包含数据。
我想了一会儿,发现原子操作,如果仔细使用会有所帮助。我的实现如下图所示。由于队列中已经存在数据,因此我没有实现 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 中。
我有以下问题:
上面的实现有问题吗?
还有哪些其他方法可以实现无锁消费者队列?
【问题讨论】:
-
“实现无锁消费者队列的其他方法有哪些?”见
java.util.concurrent.ConcurrentLinkedQueue -
“没有消费线程被阻塞”——如果队列变空,你希望消费线程做什么?
-
@AlexeiKaigorodov 假设队列有无限数据。此外,问题更多是关于如何在不使用同步的情况下以无锁方式使用它。
-
@YugSingh 我的意思是,当生产者速度慢而消费者速度快时,队列就会变空。如果不阻止,您希望消费者在这种情况下应该做什么?睡觉和投票?还是在生产下一个项目之前浪费 CPU 周期?
标签: java multithreading queue lock-free