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

欢迎!请参阅关于页面以了解更多关于如何使用本网站的信息。

0 投票
Collections

如果将(可变的)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) () nil)
`

方法: 在将其转换为数组之前将 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 投票
by

评论者:alexmiller

我想说的是,我们不应该为了使任意的Java集合更安全而牺牲持久化集合的性能。但是,在不影响持久化集合性能和/或更新文档字符串的情况下使其更安全可能仍然有用。

0 投票
by

评论者:bronsa

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

0 投票
by

评论者:alexmiller

嗯,这基本上是真的。之前的用法并没有强制实现整个序列,只是第一个元素。从这个快速测试来看,在集合上额外的成本似乎很小(向量序列实际上由于其结构而更快)。

0 投票
by

评论者:stu

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

0 投票
by
参考:[链接到CLJ-1763](https://clojure.atlassian.net/browse/CLJ-1763)(由bronsa报告)
...