Add the first element to a ConcurrentLinkedQueue atomically

余生长醉 提交于 2019-12-22 10:56:51

问题


I want to use a ConcurrentLinkedQueue in an atomic lock-free manner:

Several concurrent threads push events into the queue and some other thread will process them. The queue is not bound and I don't want any thread to wait or get locked. The reading part however may notice that the queue got empty. In a lock free implementation the reading thread must not block but will just end its task and proceeds executing other tasks (i.e. as an ExecutorService). Thus the writer pushing the first new event into an empty queue must become aware about it and should restart the reader (i.e. by submitting a new Runnable to the ExecutorService) to process the queue. Any further threads submitting a second or third event won't care about, as they may assume some reader was already prepared/submitted.

Unfortunately the add() method of ConcurrentLinkedQueue always returns true. Asking the queue if isEmpty() before or after adding the event won't help, as it is not atomic. Should I use some additional AtomicInteger for monitoring the queue size() or is there some smarter solution for that?

Dieter.


回答1:


Using of AtomicInteger for resolving submit contention is more efficient than locks or synchronized block.

  • Here is an example how it can be implemented with Java.

  • Also there is more efficient structure for multi-producer / single-writer queue than ConcurrentLinkedQueue.

  • Example of using it for actor implementations.

  • Another example.




回答2:


I don't quite understand why you wouldn't just use an ExecutorService directly for this. It uses a BlockingQueue internally and takes care of all of the signaling itself.

// open ended thread pool
ExecutorService threadPool = Executors.newFixedThreadPool(1);
for (Job job : jobsToDo) {
    threadPool.submit(new MyJobProcessor(job));
}

Unless you have good reasons, I would not rewrite the same logic yourself.

If you are trying to make use of dormant threads somehow, I would strongly recommend not bothering. Threads are relatively cheap so assigning a thread to process your queued tasks is fine. Re-using threads is unnecessary and seems like premature optimization to me.



来源:https://stackoverflow.com/questions/11654794/add-the-first-element-to-a-concurrentlinkedqueue-atomically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!