Clojure ref - 有什么理由重试此事务?

标签 clojure ref

我有这个代码:

(defn on-thread [f]
  (.start (Thread. f)))

(def myref (ref 0))

(on-thread
  #(loop [x 100]
     (when (> x 0)
       (do
         (Thread/sleep 100)
         (println "myref is:" @myref)
         (recur (dec x))))))

(on-thread 
  #(dosync
    (println "transaction1 initial:" @myref) 
    (alter myref inc)
    (println "transaction1 final:" @myref) 
    (Thread/sleep 5000)
    (println "transaction1 done")))

(on-thread 
  #(dosync
     (println "transaction2 initial:" @myref) 
     (Thread/sleep 1000)
     (alter myref inc)
     (println "transaction2 final:" @myref) 
     (println "transaction2 done")))

当我运行这个时,很明显第一个事务首先运行,并且它将 ref 的值更改为 1 - 但其他线程看不到这一点:好的,当然,因为第一个事务尚未完成然而。所以我认为此时此刻还没有“提交”回到裁判。

但此时,第一个事务进入休眠状态,在 sleep 期间,第二个事务尝试更改 ref 的值。它会被回滚,并被环境重试! 为什么? 第二个事务如何“看到”第一个事务的引用发生了(或将要发生)某些事情?

我认为,如果第二个事务能够更改 ref 的事务中值(从 0 到 1),然后 sleep 1000,最后成功提交,然后是第一个事务,那会更符合逻辑将重试。 但事实并非如此。

为什么?

最佳答案

重试第二个事务是因为当它去更改您的引用时,它发现它已经被另一个未提交的事务更改了。因此,它会重试,直到第一个事务提交。

如果万一第二个事务首先更改了引用,那么是的,第一个事务将被重试。然而,事实并非如此,因为第二个事务发生的时间比第一个事务晚得多(以 CPU 时间计算)。

关于Clojure ref - 有什么理由重试此事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10324703/

相关文章:

reactjs - React-createRef() Api-this.child.current 为 null

javascript - 在 React Native 中使用 FlatList 中的 ref

clojure - Clojure 中的自省(introspection)

clojure - 将失败(异常)传递给 promise

clojure - 可以通过 Datomic pull 语法获取枚举值吗?

java - 惯用的 Clojure 将资源从正在运行的 jar 复制到外部

shell - 使用终端命令启动 lein repl

Oracle PL/SQL : How to implement pointers to in-memory record types

c++ - C++ 中的 'ref' 和 'sealed' 关键字是什么?

c# - 指针是不安全的,但我不明白 ref