2024 Clojure状态调查! 中分享您的想法。

欢迎!请参阅关于页面以获得更多关于此页面如何工作的信息。

0
集合

如果将暴露其后存储数组的(可变的)Java集合传递给c.c/sort的多个线程中,该集合将在多个线程中并发修改。

`
user=> (def q (java.util.concurrent.ArrayBlockingQueue. 1))

'user/q

user=> (future (loop [] (.add q 1) (.remove q 1) (recur)))

object[clojure.core$future_call$reify__4393 0x4769b07b {:status :pending, :val nil}]

user=> (take 3 (distinct (repeatedly #(sort q))))
((1) () null)
`

方法:在将其转换为数组之前,将coll转换为序列,从而保留原始集合。

补丁:0001-CLJ-1763-make-sort-thread-safe.patch

其他方法

  1. 在sort中记录,与Java数组类似,Java由数组支持的集合会就地修改。
  2. 将RT.toArray()更改为从(非IPersistentCollection)Java集合中返回的数组进行防御性复制。这个方法从多个路径调用,因此有多个潜在的结果。
  3. 对于非Clojure集合,也可以使用Collections.sort()代替将它们倾倒到数组并使用Arrays.sort()。

6 答案

0

评论者:alexmiller

文档字符串说“如果coll是一个Java数组,它将被修改。为了避免这种情况,请对一个数组的副本进行排序。”这在这种情况下看起来也是很好的建议。

创建输入集合的序列视图将显着改变性能特征。

0

评论者:alexmiller

我猜我想说的是,为了使任意的Java集合更安全,我们不应该使持久集合的性能变差。但这仍然可能在不妨碍持久集合性能和/或更新文档字符串的情况下使其更安全。

0

评论者:bronsa

Alex,没有创建额外的序列,该seq调用已经存在了

0

评论者:alexmiller

嗯,这是有一定道理的。以前的用法并没有迫使整个seq实现,只是第一个元素。话虽如此,从快速测试来看,在集合上的额外成本似乎很小(由于结构,向量序列实际上更快)。

0

评论者:stu

我认为这应该是一个文档字符串更改,如果有什么不同的话。

0
参考:https://clojure.atlassian.net/browse/CLJ-1763(由bronsa报告)
...