【问题标题】:Atomic way to reorder keys in a ConcurrentSkipListMap / ConcurrentSkipListSet?在 ConcurrentSkipListMap / ConcurrentSkipListSet 中重新排序键的原子方式?
【发布时间】:2013-03-08 14:17:20
【问题描述】:

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

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

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

如果有人可以为这种类型的操作提出更好的数据结构,我也全神贯注!

【问题讨论】:

  • 这个设计会让我很紧张。比较器不应随时间而改变。
  • 对于需要维护一组顺序可能随时间变化的对象的东西,您有什么建议?
  • 一个列表,每次都使用新的比较器进行排序,可能,或者,我会编辑我的 StackOverflow 问题,为我们提供有关使您需要这种数据结构的问题的更多详细信息。 ;)
  • 这就是为什么:stackoverflow.com/questions/14805852/…。目前我只是在构建一个纯 java 版本。
  • 在那个答案中,你为什么关心它是否在某些 ~Xms 的列表中?如果它排序较低,那很好。如果还不行那就好了。我不明白为什么它必须总是在列表中。从列表中删除它还可以帮助您不必在对象本身上进行同步。如果您不将其从列表中删除以对其进行处理,您如何停止线程之间的 ++ 竞争条件?

标签: java data-structures concurrency sortedmap concurrentskiplistmap


【解决方案1】:

有没有一种方法可以使用它们原子地删除一个键并用另一个键替换它,就像我在上面所做的操作一样,这样其他迭代线程就不会错过该项目,而不必使用同步块?

简短的回答是否定的。如果您需要删除并重新插入,我知道的任何集合都没有原子方法可以做到这一点。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-28
    • 2017-12-22
    • 2020-05-16
    • 1970-01-01
    相关资源
    最近更新 更多