我有这段代码:
(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,然后最终成功提交,那么第一个事务就更合乎逻辑了将被重审。 但事实并非如此。
为什么?
答案 0 :(得分:2)
重试第二个事务,因为当它改变你的ref时,它会发现它已被另一个未提交的事务更改。因此,在第一个事务提交之前重试它。
如果第二次交易有可能首先改变了ref,那么是的,第一次交易将被重试。但是,情况并非如此,因为您的第二个事务发生在第一个事务之后(在CPU时间内)。