Clojure ref - 重试此交易的任何理由?

时间:2012-04-25 22:25:19

标签: 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 - 但是其他线程看不到:好吧,当然,因为第一个事务还没有完成然而。所以我想现在还没有“提交”回到裁判。

但此时,第一个事务进入休眠状态,当它处于休眠状态时,第二个事务会尝试改变ref的值。它会被回滚,并由环境重新开始! 为什么? 第二次交易是如何“看到”的,第一次交易的参与事件发生了(或将要发生)?

我认为如果第二个事务能够改变ref的事务内值(从0到1)然后再睡眠1000,然后最终成功提交,那么第一个事务就更合乎逻辑了将被重审。 但事实并非如此。

为什么?

1 个答案:

答案 0 :(得分:2)

重试第二个事务,因为当它改变你的ref时,它会发现它已被另一个未提交的事务更改。因此,在第一个事务提交之前重试它。

如果第二次交易有可能首先改变了ref,那么是的,第一次交易将被重试。但是,情况并非如此,因为您的第二个事务发生在第一个事务之后(在CPU时间内)。