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 :m2 :j2 :j1 :m1 :m2 :j2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :j1 :j2 :m2 :m1 :j1 :j2 :m2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :2 :j1 :j3]


这个程序有时会很快终止,但有时会因为几十或几百次的尝试而延迟几秒钟。

{{(ensure ref)}}以一种方式表现出活锁,而这种方式与等价的{{(ref-set ref @ref)}}不同,因为只有后者支持闯入。随着{{ref-set}},由于闯入,最终旧事务将会获胜。在{{ensure}}中,没有闯入,因为两个事务都尝试获得由另一个事务({{ensure}})持有的 ref 的写锁({{ref-set}})。两个事务都将空闲100毫秒的超时时间,然后同时重新尝试。

这可能是对文档的增强。句子“允许比(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 提出)
...