java动态比较器,可与concurrentskiplistset正常工作

6rqinv9w  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(303)

我试着用 queue = new ConcurrentSkipListSet<Task>(Comparators.comparing(Task::priority)) 作为具有唯一元素的并发优先级队列(请参阅此处的类似讨论),但我需要不时更改任务的优先级。
显然,当元素在集合中时改变它们的优先级就是打开一个蠕虫的罐头;幸运的是,我只需要在将它们从 queue ,然后再重新提交。更确切地说,我使用 pollFirst()queue ,我可能需要在更新其优先级(优先级较低)后重新提交。
如果这是一个串行实现,那么当元素在集合之外时更改它们的优先级应该没有问题。
使用并发访问执行此更新的线程安全方式是什么?能保证吗 task = queue.pollFirst() 以前发生过 task.priorityUpdate() ,发生在 queue.add(task) ?

j8ag8udp

j8ag8udp1#

所有并发集合都在元素put和元素get之间建立关系之前发生。
问题是,当他们在队列中时,您需要更改优先级,然后将他们取出并放回队列,因为这是唯一的方法;然后,一个并发线程可能同时放置同一个元素,这样您就失去了修改。在这种情况下,需要进一步同步。
但是,如果您要取出元素,更改它们的优先级,然后才评估是否应该将它们放回,那么在并发集合的保证足以确保正确性之前就会发生,您不需要做任何其他事情。
add()pollFirst() 有一个before关系,所以在线程中创建的对象调用 add() 对线程调用可见 pollFirst() .
pollFirst()add() 没有。但是,如果您更改了优先级,然后 add() 对于同一线程,不需要进一步的内存约束。
如果你以后打电话 pollFirst() 从另一个线程来看,在 add() 以及 pollFirst() 将保证在调用之前对对象进行更新 add() 是可见的。

相关问题