本文介绍了ConcurrentLinkedQueue $ node保留在堆中remove()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个多线程应用程序编写和读取ConcurrentLinkedQueue,这在概念上用于回退列表/表中的条目。我最初使用一个ConcurrentHashMap为这,工作很好。需要跟踪订单条目的新要求,因此可以根据一些条件以最旧的第一顺序删除它们。 ConcurrentLinkedQueue似乎是一个不错的选择,在功能上它工作得很好。

I have a multithreaded app writing and reading a ConcurrentLinkedQueue, which is conceptually used to back entries in a list/table. I originally used a ConcurrentHashMap for this, which worked well. A new requirement required tracking the order entries came in, so they could be removed in oldest first order, depending on some conditions. ConcurrentLinkedQueue appeared to be a good choice, and functionally it works well.

可配置的条目数量保存在内存中,当提供一个新条目时,到达时,以最先排序的顺序搜索可以删除的队列。某些条目不会被系统删除并等待客户端的交互。

A configurable amount of entries are held in memory, and when a new entry is offered when the limit is reached, the queue is searched in oldest-first order for one that can be removed. Certain entries are not to be removed by the system and wait for client interaction.

发生的情况是,我在队列的前面有一个条目,说100K条目前。队列看起来具有有限数量的配置条目(size()== 100),但是当概要分析时,我发现在内存中有〜100K ConcurrentLinkedQueue $ Node对象。这似乎是通过设计,只是看了ConcurrentLinkedQueue的来源,一个删除只是删除对正在存储的对象的引用,但使链接的列表在适当的迭代。

What appears to be happening is I have an entry at the front of the queue that occurred, say 100K entries ago. The queue appears to have the limited number of configured entries (size() == 100), but when profiling, I found that there were ~100K ConcurrentLinkedQueue$Node objects in memory. This appears to be by design, just glancing at the source for ConcurrentLinkedQueue, a remove merely removes the reference to the object being stored but leaves the linked list in place for iteration.

最后我的问题:有一个更好的懒惰的方式来处理这种性质的集合?我喜欢ConcurrentLinkedQueue的速度,我只是无法承受在这种情况下似乎是可能的无限的泄漏。如果没有,我似乎需要创建第二个结构来跟踪顺序,可能有相同的问题,加上同步的关注。

Finally my question: Is there a "better" lazy way to handle a collection of this nature? I love the speed of the ConcurrentLinkedQueue, I just cant afford the unbounded leak that appears to be possible in this case. If not, it seems like I'd have to create a second structure to track order and may have the same issues, plus a synchronization concern.

推荐答案

这里发生的实际情况是remove方法准备一个轮询线程以清除链接的引用。

What actually is happening here is the remove method prepares a polling thread to null out the linked reference.

ConcurrentLinkedQueue是一个非阻塞线程安全队列实现。但是,当您尝试从队列轮询节点时,它是一个双功能过程。首先你null的值,然后你null的引用。 CAS操作是不会为轮询提供immidiate解析的单个原子函数。

The ConcurrentLinkedQueue is a non blocking thread safe Queue implementation. However when you try to poll a Node from the Queue it is a two function process. First you null the value then you null the reference. A CAS operation is a single atomic function that would not offer immidiate resolution for a poll.

当轮询时发生的第一个线程将获得节点的值并且该值为空,那么该线程将尝试使引用为null。可能另一个线程将进入并尝试从队列轮询。为了确保这个队列拥有一个非阻塞属性(即一个线程的失败不会导致另一个线程的失败),新的传入线程将看到该值是否为null,如果它为空,该线程将null参考,并尝试再次对poll()。

What happens when you poll is that the first thread that succeeds will get the value of the node and null that value out, that thread will then try to null the reference. It is possible another thread will then come in and try to poll from the queue. To ensure this Queue holds a non blocking property (that is failure of one thread will not lead to the failure of another thread) that new incomming thread will see if the value is null, if it is null that thread will null the reference and try again to poll().

所以你看到的发生这里是删除线程正在准备任何新的轮询线程空参考。试图实现非阻塞删除功能我认为几乎不可能,因为这将需要三个原子功能。 null值引用所述节点的空值,最后是从那个节点parent到其后继的新引用。

So what you see happening here is the remove thread is simply preparing any new polling thread to null the reference. Trying to achieve a non blocking remove function I would think is nearly impossible because that would require three atomic functions. The null of the value the null referencing to said node, and finally the new reference from that nodes parent to its successor.

回答你最后一个问题。有没有没有更好的方法来实现删除和维护队列的非阻塞状态unforutnalty。这至少是在这一点上。一旦处理器开始用2和3方式套管,那是可能的。

To answer your last question. There is unforutnalty no better way to implement remove and maintain the non blocking state of the queue. That is at least at this point. Once processors start comming out with 2 and 3 way casing then that is possible.

这篇关于ConcurrentLinkedQueue $ node保留在堆中remove()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 21:17