【问题标题】:Race condition in Clojure stm?Clojure stm中的竞争条件?
【发布时间】:2015-02-01 11:51:23
【问题描述】:

您好,我正在阅读 clojure 的书,在关于 STM 的部分中,他们有 2 个事务的图像,其中 A 最初从 ref 中检索与 B 相同的值,然后事务 A 和 B 都进行计算但是 A 先完成并提交到变量,因此 B 必须重试。

但我正在思考的是,如果 B 会用 A 的提交重试。如果是这样的话,如果情况相反呢?那么最终的值就会有很大的不同。

这似乎是一个被忽视的简单危险,我相信我并不完全理解它。请帮我解开这个问题。

【问题讨论】:

    标签: clojure race-condition stm


    【解决方案1】:

    我们来看例子:

    (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 个)并观察 ref 的最终值。事实上,每次运行的结果都不同:

    => (test-trans)
    2418
    => (test-trans)
    2380
    => (test-trans)
    1804
    => (test-trans)
    4210
    

    其实这是正确的行为。 STM 保证代码将在没有锁的情况下执行,并且以原子方式应用更改(它们不能仅部分应用)。但是,它不能保证我们在不同的交易顺序下会有相同的结果。

    Clojure 提供了出色的并行编程工具,大大简化了正确代码的编写。但是避免这种竞争条件是开发人员的责任(事实上,这种情况是糟糕的系统设计的明显迹象)。

    另一个来自 SQL 的例子:

    DELETE FROM tbl WHERE col=1
    UPDATE tbl SET col=2 WHERE col=1
    

    如果这些查询是并行执行的,那么无论事务使用什么隔离级别 - 结果都将取决于顺序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-07
      • 2011-07-17
      • 2013-02-27
      • 2021-04-16
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多