2012-04-16 38 views
4

我在clojure.org/refs讀到STM交易中的參考是否真的一致?

參考文獻的所有讀取會看到「參考世界的一致性快照作爲交易的起點(其「讀點」)。交易將看到它所做的任何更改。這被稱爲交易中的價值。

還有一個關於維基百科Snapshot Isolation的鏈接,暗示任何數量的refs的讀取在事務開始後都會彼此一致。

我做了一個試驗案例...

(def r1 (ref 0)) 
(def r2 (ref 0)) 

(defn delay-then-inc-ref [id ref delay] 
    (.start 
    (Thread. 
     #((println id " start") 
      (Thread/sleep delay) 
      (dosync 
      (alter ref inc)) 
      (println id " end"))))) 

(defn deref-delay-deref [ref1 ref2 delay] 
    (.start 
     (Thread. 
      #((println "S start") 
      (dosync 
       (let [a @ref2] 
       (Thread/sleep delay) 
       (println "S r1=" @ref1))) ; @ref1 consistent with @ref2 ? 
       (println "S end"))))) 

*clojure-version* 
;=> {:major 1, :minor 3, :incremental 0, :qualifier nil} 
(deref-delay-deref r1 r2 2000) 
(delay-then-inc-ref "1" r1 500) 
(delay-then-inc-ref "2" r1 1000) 
(delay-then-inc-ref "3" r1 1500) 

輸出是:

S start 
1 start 
2 start 
3 start 
1 end 
2 end 
3 end 
r1 = 3 
S end 
nil 

r1 = 3而非r1 = 0值表明,deref-delay-deref REF1的sleep後DEREF正在復甦三個交易發生後的值。

請注意,我知道約ensure阻止在特定交易期間通過其他交易更新引用,但我不相信這適用於此處。我不在乎ref1是否會發生變化,只要我看到一個與我的交易開始時一致的值即可。

這種行爲如何符合上述參考文檔?

回答

1

事實證明,如果裁判有一定的歷史,它的行爲如我所料,所以改變裁判的聲明添加:min-history,然後設置兩個裁判如圖所示,似乎使其工作....

(def r1 (ref 0 :min-history 5)) 
(def r2 (ref 0 :min-history 5)) 

(dosync 
(ref-set r1 0) 
(ref-set r2 0)) 

然後輸出爲:

S start 
1 start 
1 end 
2 start 
2 end 
3 start 
3 end 
S r1= 0 
S end 
nil 

閱讀here,很清楚發生了什麼事情。讀取事務正在重新啓動,因爲事務啓動之前ref歷史記錄中沒有條目。爲了confim我增加了一些記錄:

(defn deref-delay-deref [ref1 ref2 delay] 
    (.start 
     (Thread. 
      #((println "S start") 
      (dosync 
       (println "transaction starting") 
       (let [a @ref2] 
       (Thread/sleep delay) 
       (println "S r1=" @ref1))) ; should be consistent with @ref2 
      (println "S end"))))) 

輸出沒有歷史器官功能障礙綜合徵:

S start 
transaction starting 
1 start 
2 start 
3 start 
1 end 
2 end 
3 end 
transaction starting 
S r1= 3 
S end 

,並與歷史MODS:

S start 
transaction starting 
1 start 
2 start 
3 start 
1 end 
2 end 
3 end 
S r1= 0 
S end 
nil 

UPDATE:原來我的回答以上由於測試用例的人爲特性而引起分心。在現實世界中,事務是否重新啓動並不重要,因爲事務必須被寫入,以便它們可重新啓動。運行時不提供有關只讀事務是否在有/無歷史記錄時完成的保證。相反,它可以做任何必要的事情來完成交易的世界,交易代碼必須牢記在心。更詳細的討論here

我要離開上面的參考。

+0

因爲我回答了我自己的問題,我將這個答案標記爲社區wiki,根據meta.stackoverflow.com提供的禮儀建議 – sw1nn 2012-04-16 20:14:26