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

欢迎!有关如何使用本服务的更多信息,请参阅关于页面。

0
Clojure
以下程序演示了在使用{{ensure}}时发生的活锁。


(let [cats (ref 1)
      dogs (ref 1)
      events (atom [])
      john (future
               (dosync
                 (swap! events conj :j1)
               (when (< (+ @cats (ensure dogs)) 3)
                 (swap! events conj :j2)
                 (ref-set cats 2))
               (swap! events conj :j3)))
      mary (future
               (dosync
               (swap! events conj :m1)
               (when (< (+ (ensure cats) @dogs) 3)
                 (swap! events conj :m2)
                 (ref-set dogs 2))
               (swap! events conj :m3)))]
  @john @mary @events)
; => [:m1 :j1 :m2 :j2 :j1 :m1 :j2 :m2 :j1 :m1 :j2 :m2 :m1 :j1 :j2 :m2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :j1 :j2 :m2 :j1 :m1 :j2 :m2 :m1 :j1 :j2 :m2 :j1 :m1 :m2 :j2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :j1 :j2 :m2 :j1 :m1 :j1 :m2 :j2 :j1 :m3 :j1 :j3]


此程序有时会非常快速终止,但在交易重试数十或数百次后,有时会有几秒钟的延迟。

{{(ensure ref)}}以一种{{(ref-set ref @ref)}}所不具有的方式显示活锁,因为只有后者支持闯关。有了{{ref-set}},较旧的交易最终会胜出,这得益于闯关。有了{{ensure}},由于两个交易都试图获取由另一个交易({{ensure}})持有的读锁的ref的写锁({{ref-set}}),因此没有闯关。两个交易都将闲置整整100ms的超时时间,然后将同时重试。

这可能是对文档的一个增强。句子“比(ref-set ref @ref)具有更高的并发性”在一般情况下可能不正确(无论如何,太笼统了,帮助不大)。{{(ref-set ref @ref)}}比{{(ensure ref)}}更安全。

2 个答案

0

评论:glts

来自旧邮件列表讨论(链接:https://groups.google.com/d/msg/clojure/H676Em2zvhM/oXqKS-OvAgAJ 文字:这里)和(链接:https://groups.google.com/d/msg/clojure-dev/OC3N4O1jy9Q/QuH9iYT7DgAJ 文字:这里)。

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