请在 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

评论者:alexmiller

我认为我在说的应该是,我们不应该为了使任意Java集合更安全而降低持久集合的性能。但仍然有必要在不影响持久集合性能的情况下使它更安全,或者更新文档字符串。

0

评论者:bronsa

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

0

评论者:alexmiller

嗯,这也是对的。之前的用法并迫使整个序列实际化,仅仅是第一个元素。但言归正传,从快速测试来看,在集合上额外的成本似乎很小(由于它们的结构,向量序列实际上更快)。

0

评论者:stu

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

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