如果将一个(可变的)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
其他方法
- 在 sort 中记录,与 Java 数组一样,Java 数组支持的集合在原地修改。
- 将 RT.toArray() 改为从非 IPersistentCollection Java 集合中返回的数组进行防御性复制。这有几个潜在的后果,因为这个方法从几个路径中被调用。
- 对于非 Clojure 集合,也可以使用 Collections.sort() 而不是将它们倾倒为数组并使用 Arrays.sort()。