您好我正在阅读本书的快乐,并且在关于STM的部分中,他们有2个事务的图像,其中A最初从参考中检索与B相同的值,然后事务A和B都进行计算但是A首先完成并提交变量,因此B必须重试。
但我正在思考的是B是否会重审A的提交。如果是这样的话那么如果相反呢?那么最终的价值将明显不同。
这似乎很容易被忽视,我相信我完全不理解它。请帮我解开这个。
答案 0 :(得分:6)
让我们看看例子:
(defn test-trans []
(let [x (ref 1)
t-inc #(dosync (alter x inc))
t-mul #(dosync (alter x (partial * 2)))
fns (flatten (repeat 10 [t-mul t-inc]))]
(last (pmap (fn [f] (f)) fns))
@x))
这里我们有2个事务函数 - 将x
增加1并将x
乘以2.我们并行应用20个这样的函数(每种函数10个)并观察{{1}的最终值}。实际上每次运行的结果都不同:
ref
实际上这是正确的行为。 STM保证代码将在没有锁的情况下执行,并且以原子方式应用更改(它们不能仅部分应用)。但是,它并不能保证我们对不同的交易顺序会有相同的结果。
Clojure提供了很棒的并行编程工具,可以简化大量正确代码的编写。但是避免这种竞争条件是开发人员的责任(事实上,这种情况显然是系统设计不良的标志)。
SQL的另一个例子:
=> (test-trans)
2418
=> (test-trans)
2380
=> (test-trans)
1804
=> (test-trans)
4210
如果这些查询是并行执行的,那么无论什么隔离级别将用于事务 - 结果将取决于订单。