我在clojure.org/refs上读到
从事务的起点(它的“读取点”)开始,所有对 Refs 的读取都将看到“Ref world”的一致快照。事务将看到它所做的任何更改。这称为交易中价值。
在 wikipedia上还有一个指向Snapshot Isolation的链接,这意味着一旦事务开始,读取任意数量的 ref 将彼此一致。
我做了一个测试用例...
(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 的 deref 中,在三个事务发生后sleep
选择 r1 的值。delay-then-inc-ref
请注意,我知道ensure
要防止在特定事务期间其他事务对 refs 进行更新,但我认为这不适用于此处。ref1
只要我看到与我的交易开始一致的值,我不在乎是否发生变化。
这种行为如何符合上述参考文档?