Recently I came across this question : There are say 3 consumer threads and need to implement a lock-free queue(can't use synchronization) so that no consuming thread is blocked. Assume that queue already contains the data.
I thought about it for a while and came across Atomic operations which if used carefully can help. My implementation is as shown below. As data is already there in queue I have not implemented the enqueue
method and populating the array inside the constructor.
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();
}
}
I have executed the above program and the result shows that the all 3 consumers are consuming the data albeit out of order and some threads are consuming more data than the other threads but I don't see any of the data appearing multiple times in the o/p.
I have the following questions:
Is there any issue in the above implementation?
What are the other ways to implement lock-free consumer queue?
java.util.concurrent.ConcurrentLinkedQueue
– Andreas