知识库--Handling Write Skew Anomaly 处理写偏差(123)

案例:在确保两个账户总额大于1000的情况下,可以执行取款操作;
两个账户同时(concurrency)分别进行取款时出现问题

错误代码:

    (def checking-balance (ref 500))
    (def savings-balance (ref 600))

    (defn withdraw-account [from-balance constraining-balance amount]
        (dosync
            (let [total-balance (+ @from-balance @constraining-balance)]
            (. Thread sleep 1000)
            (if (>= (- total-balance amount) 1000)
                (alter from-balance - amount)
            (println "Sorry, can't withdraw due to constraint violation")))))

    (println "checking-balance is" @checking-balance)
    (println "savings-balance is" @savings-balance)
    (println "Total balance is" (+ @checking-balance @savings-balance))

    (future (withdraw-account checking-balance savings-balance 100))
    (future (withdraw-account savings-balance checking-balance 100))

    (. Thread sleep 2000)

    (println "checking-balance is" @checking-balance)
    (println "savings-balance is" @savings-balance)
    (println "Total balance is" (+ @checking-balance @savings-balance))

We start with the given balances for the two accounts:

checking-balance is 500
savings-balance is 600
Total balance is 1100
checking-balance is 400
savings-balance is 500
Total balance is 900

正确代码:

(defn withdraw-account [from-balance constraining-balance amount]
        (dosync
             (let [total-balance (+ @from-balance (ensure constraining-balance))]
            (. Thread sleep 1000)
             (if (>= (- total-balance amount) 1000)
                 (alter from-balance - amount)
                 (println "Sorry, can't withdraw due to constraint violation")))))

结果:

checking-balance is 500
savings-balance is 600
Total balance is 1100
checking-balance is 500
savings-balance is 500
Total balance is 1000
Sorry, can't withdraw due to constraint violation

秘密:
On line 3, we called ensure() on the value constraining-balance, which we read but don’t modify in the transaction. At this point, STM places a read lock on that value, preventing other transactions from gaining a write lock. When the transaction nears completion, STM releases all read locks before it performs the commit. This prevents any possibility of deadlock while increasing concurrency.

Clojure STM is the aspirin of the programming concurrency world—it can remove so much pain. If we forget to create a transaction, we’re sternly rebuked For simply placing dosync at the right place, we’re rewarded with high concurrency and consistency between threads. Such low ceremony, concise, highly expressive, and very predictable behavior all make Clojure STM an option worth serious consideration.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值