Ced*_*tin 3 concurrency multithreading atomic clojure
我今天在IRC的#clojure频道上讨论过这个问题,但是我想在这里详细介绍一下.基本上,为了更好地理解原子swap!,deref和Clojure的并发作为一个整体,我想尝试写一个函数,它不仅返回被交换,在使用的价值swap!,也表明了换出的值.
(def foo (atom 42))
.
.
.
((fn [a]
(do
(println "swapped out: " @a)
(println "swapped in: "(swap! a rand-int)))) foo)
Run Code Online (Sandbox Code Playgroud)
可以打印:
swapped out: 42
swapped in: 14
Run Code Online (Sandbox Code Playgroud)
但是,如果另一个线程swap!在@a deref和调用之间执行相同的原子,swap!那么我可能会交换一个不是42的值.
如何编写一个能正确回放两个值(交换掉和交换掉)的函数?
我并不关心原子确实改变的各种值:我想知道的是所交换的值是多少.
这可以使用保证不会死锁的代码编写,如果是这样,为什么?
Stu*_*rra 13
Clojure swap!只是一个旋转的比较和设定.您可以定义一个返回您喜欢的替代版本:
(defn alternate-swap [atom f & args]
(loop []
(let [old @atom
new (apply f old args)]
(if (compare-and-set! atom old new)
[old new] ; return value
(recur)))))
Run Code Online (Sandbox Code Playgroud)
原子是不协调的,因此任何在其本身的交换函数之外执行此操作的尝试都可能会失败。您可以编写一个调用的函数来代替交换!它构造一个函数,在应用实际函数之前保存现有值,然后将此构造函数传递给swap!.
user> (def foo (atom []))
#'user/foo
user> (defn save-n-swap! [a f & args]
(swap! a (fn [old-val]
(let [new-val (apply f (cons old-val args))]
(println "swapped out: " old-val "\n" "swapped in: " new-val)
new-val))))
#'user/save-n-swap!
user> (save-n-swap! foo conj 4)
swapped out: []
swapped in: [4]
[4]
user> (save-n-swap! foo conj 4)
swapped out: [4]
swapped in: [4 4]
[4 4]
Run Code Online (Sandbox Code Playgroud)
这个例子打印它,将它们推送到存储在另一个原子中的更改日志也是有意义的
| 归档时间: |
|
| 查看次数: |
500 次 |
| 最近记录: |