java - 在 ConcurrentSkipListMap/ConcurrentSkipListSet 中重新排序键的原子方式?

标签 java data-structures concurrency sortedmap concurrentskiplistmap

这篇文章的摘要:我有一组订购的商品,其顺序可能会随着时间的推移而改变。我需要能够从多个线程迭代这个集合,每个线程可能还想更新项目的顺序。

例如,多个线程需要以某种任意排序的顺序访问String键。它们的字符串不是根据其自然顺序排序,而是根据一些可能更改的值排序(因此,是一个自定义的比较器)。我最初的实现是使用 TreeSet 并在其上进行同步。如果任何键需要重新排序,线程将从映射中删除该键,更新比较值,然后重新插入该键。为了实现这一点,键是 native String,但比较器可以访问值。这是一种奇怪的安排,其中键的顺序可能会随着时间的推移而改变,但由于更改后的键总是在更改时被删除并重新插入,因此它似乎有效。 (我想如果 String 被包装在另一个对象中也可以工作。)

我最近意识到 ConcurrentSkipListSet/ConcurrentSkipListMap 实现基本上是线程安全的排序集(分别是映射。)似乎我现在可以迭代键,而不必锁定整个数据结构。但是,有没有一种方法可以使用它们以原子方式删除一个键并将其替换为另一个键,就像我上面所做的操作一样,以便其他迭代线程不会错过该项目,并且不必使用 synchronize block ?

如果有人可以为此类操作提出更好的数据结构,我也洗耳恭听!

最佳答案

is there a way I can use them to atomically remove a key and replace it with another, like the operation I was doing above, so that other iterating threads don't miss the item, and without having to use synchronize blocks?

简短的回答是否定的。如果您需要删除并重新插入,据我所知,没有原子方法可以对任何集合执行此操作。

也就是说,一种可能是您在将项目从跳过列表中删除之前重新插入该项目。这会导致重复,但可能比丢失条目更容易处理。您可以在更改对象后重新插入它,这样它就会以不同的方式排序。这假设该对象也将是不相等的。但如果处理列表的其他线程无法处理重复项,那么我认为您是 SOL。

关于java - 在 ConcurrentSkipListMap/ConcurrentSkipListSet 中重新排序键的原子方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15507418/

相关文章:

java - 在 HttpClient 4.0 中设置 HttpParams 对象

java - 意外复制其他对象的行为

c++ - A* 开放集的最佳数据结构是什么?

java - 为什么 LinkedBlockingQueue 的 put() 中有一个 while 循环

swift - 标准 Swift 数学函数中的运算次数

java - 在Java中的不同线程中运行后台进程

java - 从 ResultSet SQL 结果填充数组

c# - 嵌套分组策略/算法c#

algorithm - 如何测试整数范围是否与整数列表重叠?

c - 哪些绿色线程库可用于 C,可以匹配 Haskell 绿色线程的性能和易用性?