gpt4 book ai didi

java - 与 ConcurrentSkipListSet 一起正常工作的即时比较器

转载 作者:行者123 更新时间:2023-12-03 12:47:10 24 4
gpt4 key购买 nike

我正在尝试使用

queue = new ConcurrentSkipListSet<Task>(Comparators.comparing(Task::priority))

作为具有独特元素的并发优先级队列(参见类似的讨论 here ),但我需要不时更改任务的优先级。

显然,在集合中时更改元素的优先级无异于打开一堆蠕虫;幸运的是,我只需要在将它们从 queue 中删除后更改它们的优先级,并在重新提交之前。更准确地说,我使用 pollFirst()queue 弹出一个元素,我可能需要在更新其优先级(优先级较低)后重新提交。

如果这是一个串行实现,当元素在集合之外时更改元素的优先级应该没有问题。

通过并发访问执行此更新的线程安全方式是什么?是否足以保证

task = queue.pollFirst()发生在 task.priorityUpdate() 之前, 发生在 queue.add(task) 之前?

最佳答案

所有并发集合在元素放置和元素获取之间建立先行关系。

问题是,如果您需要在队列中更改优先级,然后将它们取出并放回队列中,因为这是唯一的方法;然后,并发线程可能同时放置相同的元素,然后您将丢失修改。在这种情况下,将需要进一步同步。

但是,如果您要取出元素,更改它们的优先级,然后才评估是否应该将它们放回原处,并发集合的 happen-before 保证足以确保正确性,您无需执行任何其他操作。

add()pollFirst()存在happens-before关系,所以在调用add()的线程中创建的对象> 对调用 pollFirst() 的线程可见。

pollFirst()add() 没有。但是,如果您更改优先级,然后从同一线程调用 add(),则不需要进一步的内存限制。
如果稍后从另一个线程调用 pollFirst()add()pollFirst() 之间的先行关系将保证更新到调用 add() 之前的对象是可见的。

关于java - 与 ConcurrentSkipListSet 一起正常工作的即时比较器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65464750/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com