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

来源:互联网 发布:汽车ecu编程器 编辑:程序博客网 时间:2024/06/05 20:35

案例:在确保两个账户总额大于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 500savings-balance is 600Total balance is 1100checking-balance is 400savings-balance is 500Total 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 500savings-balance is 600Total balance is 1100checking-balance is 500savings-balance is 500Total balance is 1000Sorry, 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.

0 0
原创粉丝点击