2 回答
TA贡献1804条经验 获得超7个赞
首先,让我们陈述一个显而易见的事实 - 最好的解决方案是避免编写任何此类自定义类。也许像java.util.concurrent.LinkedTransferQueue这样简单的东西也可以工作,并且不那么容易出错。如果 a 不起作用,那么 LMAX 干扰器或类似的东西呢?您是否看过现有的解决方案?LinkedTransferQueue
如果你仍然需要/想要一个自定义解决方案,那么我有一个稍微不同的方法的草图,一个可以避免复制的方法:
这个想法是让操作围绕一些原子变量旋转,试图设置它。如果线程设法设置了它,那么它将获得对当前队列的独占访问权限,这意味着它可以追加到它。追加后,它会重置原子变量以允许其他线程追加。它基本上是一个旋转锁。这样,线程之间的争用就会在追加到队列之前发生,而不是在追加到队列之后。put
TA贡献1868条经验 获得超4个赞
我需要在每次写入尝试时复制实际队列
你的想法听起来像RCU(https://en.wikipedia.org/wiki/Read-copy-update)。Java被垃圾回收通过为您解决解除分配问题使RCU变得更加容易(我认为)。
如果我从你的问题的快速浏览中正确理解,你的“读者”实际上想为自己“声称”容器的整个当前内容。这也使它们有效地成为编写者,但是它们不是读取+复制,而是可以构造一个空容器,并原子地交换顶级引用以指向该容器。(因此,声明旧容器进行独占访问。
RCU的一大好处是容器数据结构本身不必到处都是原子的。一旦你有对它的引用,就没有其他人在修改它。
唯一棘手的部分是当作家想要将新内容添加到非空容器中时。然后,您复制现有容器并修改副本,并尝试将更新后的副本 CAS(比较交换,即)到共享的顶级中。compareAndSet()
AtomicReference
一个作家不能只是无条件地交换,因为它可能最终会得到一个非空的容器,无处放它。除非编写器可以坚持一批工作并旋转等待读取器清空队列...
我在这里假设你的作家有一批工作可以同时排队;否则RCU对作家来说可能太贵了。很抱歉,如果我错过了您的问题中的一个细节,可以排除这一点。我不经常使用Java,所以我只是快速编写这个,以防万一它有帮助。
添加回答
举报