我还找到了解决我特定问题的方法。我将将其修订成一般问题声明,以便可能是一个需要支持的合理用例。
因此,基本问题与swap!解决冲突的方式有关。我用以下代码进行了演示
(def d (atom 0))
(pmap (fn [_] (swap! d (fn [x] (println "x:" x) (inc x)))) (range 10))
x: 0
0
0
1
0
1
2
1
1
2
3
2
4
2
5
2
5
6
7
6
5
8
7
7
8
8
9
=> (1 10 2 9 4 3 6 5 8 7)
最终结果正确(10个值递增),但为了达到这个结果,交换函数被调用了超过30次,并且有许多内部状态的重复(例如,“0”)。我可以推测,在内部,swap! 并行运行函数,但在出现冲突时重新播放一些。
如果我们把这转化为缓存,有一些情况下,并行实例的 c/through-cache see has? = false,因此运行了缺失分支,然后在更新冲突时重新执行。
这没有问题,尽管我可能还是会认为,至少文档字符串很混乱,也许应该指出这仅适用于单线程执行。
我将提出第二个评论,其中包含一个一般性问题陈述以及解决问题的潜在方案。