引用在STM事务中是否真的一致? [英] Are refs really consistent within a STM transaction?

查看:125
本文介绍了引用在STM事务中是否真的一致?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 clojure.org/refs 上读到

所有引用的引用将在事务开始点(其读取点")上看到引用世界"的一致快照.事务将看到它所做的任何更改.这就是所谓的交易中价值.

All reads of Refs will see a consistent snapshot of the 'Ref world' as of the starting point of the transaction (its 'read point'). The transaction will see any changes it has made. This is called the in-transaction-value.

在Wikipedia上也有指向快照隔离的链接,这意味着可以读取任意数量的引用.交易开始后,彼此将保持一致.

There's also a link to Snapshot Isolation on wikipedia that implies that reads of any number of refs will be consistent with each other once a transaction has started.

我做了一个测试用例...

I made a test case...

(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中,在sleep之后的ref1的deref在选择三个delay-then-inc-ref事务具有的r1 之后的值发生.

The value of r1 = 3 rather than r1 = 0 suggests that in deref-delay-deref the deref of ref1 after the sleep is picking the value of r1 after the three delay-then-inc-ref transactions have occurred.

请注意,我知道ensure prevent 会在特定事务期间更新其他事务对引用的引用,但是我认为这并不适用.我不在乎ref1是否更改,只要我看到与我的交易开始一致的值即可.

Note that I know about ensure to prevent updates to refs by other transactions during a particular transaction, but I don't believe that applies here. I don't care if ref1 changes as long as I see a value consistent with the start of my transaction.

此行为与上述参考文档如何匹配?

How does this behaviour fit with the above referenced documentation?

推荐答案

事实证明,如果ref具有某些历史记录,它的行为将与我期望的一样,因此更改ref声明以添加:min-history,然后将两个ref设置为如图所示,似乎可以正常工作....

It turns out that if the ref has some history it behaves as I expect, so changing the ref declaration to add a :min-history and then setting both refs as shown, seems to make it work....

(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

此处中阅读,很清楚发生了什么.读取事务正在重新启动,因为从事务开始之前的引用历史记录中没有任何条目.为表示感谢,我添加了更多日志记录:

Reading here, it's clear what's going on. The read transaction is restarting because there is no entry in the ref history from before the transaction started. To confim I added some more logging:

(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

以及历史记录模式:

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

更新:事实证明,由于测试用例的人为性质,我的上述回答令人分心.在现实世界中,事务是否重新启动无关紧要,因为事务必须以可重新启动的方式编写.运行时不保证在存在/不存在历史记录时只读事务是否将完成.相反,它可以做任何必要的事情来完成交易的世界,并且必须牢记这一点来编写交易代码. 此处

UPDATE: It turns out my answer above is something of a distraction because of the artificial nature of the test case. In real world usage it doesn't matter whether the transaction re-starts or not, since the transactions MUST be written such that they are re-startable. The runtime provides no guarantees about whether read only transactions will complete in the presence/absence of history. Rather it can do whatever's necessary to get the world of transactions to complete and the transaction code MUST be written with this in mind. More detailed discussion here

我将上面的内容留作参考.

I'm leaving the above for reference.

这篇关于引用在STM事务中是否真的一致?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆