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


这个程序有时会非常迅速地终止,但有时由于事务尝试几十或几百次,可能会有几秒钟的延迟。

{{(ensure ref)}} 可能以{{(ref-set ref @ref)}}不可能的方式表现出死锁,因为这些后者支持barging。有了{{ref-set}},旧的交易最终由于barging而获胜。使用{{ensure}}时,没有barging,因为两个事务都试图获取由另一个事务({{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 报告)
...