clojure/core commute

点我查看原文及更多示例

(ns $clojureDoc.core.commute)
;; 使用方式:(commute ref fun & args)
;; Must be called in a transaction. Sets the in-transaction-value of
;; ref to:
;;  (apply fun in-transaction-value-of-ref args)
;;  and returns the in-transaction-value of ref.
;;  At the commit point of the transaction, sets the value of ref to be:
;;  (apply fun most-recently-committed-value-of-ref args)
;;  Thus fun should be commutative, or, failing that, you must accept
;; last-one-in-wins behavior.  commute allows for more concurrency than
;; ref-set.
;; 必须应用在事务中
;; 设定事务中的值引用:
;; 返回(apply fun in-transaction-value-of-ref args)的结果
;; 在事务提交时,设定ref的值为:(apply fun most-recently-committed-value-of-ref args)
;; 因此,commute函数会执行两次
;; 然而函数fun应该是可交换的,否则返回失败,必须处理
;; commute允许多个并发

;; sleep-print-update返回一个函数,接收一个state参数
(defn sleep-print-update
  [sleep-time thread-name update-fn]
  (fn [state]
    (Thread/sleep sleep-time)
    (println state)
    (println (str thread-name ": " state))
    (update-fn state)
    )
  )

(def counter (ref 2))

(future (dosync (commute counter (sleep-print-update 100 "Commute Thread A" inc))))
(future (dosync (commute counter (sleep-print-update 150 "Commute Thread B" inc))))
;; 输出
;; 2
;; Commute Thread A: 2
;; 2
;; Commute Thread B: 2
;; 2
;; Commute Thread A: 2
;; 3
;; Commute Thread B: 3

;; REPL中运行看出效果
;(def savings-ref-stand (ref {:balance 500}))
;(def checking-ref-stand (ref {:balance 250}))
;(:balance @savings-ref-stand)
;;; => 500
;(:balance @checking-ref-stand)
;;; => 250
;(dosync
;  (commute checking-ref-stand assoc :balance 700)
;  (throw (Exception. "Oops..."))
;  (commute savings-ref-stand assoc :balance 50)
;  )
;(:balance @savings-ref-stand)
;;; => 500
;(:balance @checking-ref-stand)
;;; => 250

猜你喜欢

转载自blog.csdn.net/sinat_37167645/article/details/93766020