clojure发送println函数
我正在尝试在事务中发送clojure发送println函数,clojure,stm,Clojure,Stm,我正在尝试在事务中发送函数println (ns com.lapots.functional.clojure.transact (:gen-class)) (defn transfer [from to amount] (alter (.balance from) - amount) (alter (.balance from) + amount)) (defrecord Account [balance]) (defn -main
函数println
(ns com.lapots.functional.clojure.transact
(:gen-class))
(defn transfer [from to amount]
(alter
(.balance from) - amount)
(alter
(.balance from) + amount))
(defrecord Account [balance])
(defn -main [& args]
(def account1 (Account. (ref 100)))
(def account2 (Account. (ref 100)))
(def trx-agent (agent 0))
(future
(dosync
(send-off trx-agent println "T2 transfer")
(Thread/sleep 5000)
(transfer account1 account2 10)))
(dosync
(println "T1 transfer")
(transfer account1 account2 10))
(shutdown-agents)
)
如果我真的喜欢这个
(println "T2 transfer")
(Thread/sleep 5000)
(send-off trx-agent println "T2 transfer")
它在事务重试时显示消息两次。因此,我决定使用代理
使副作用操作println
只运行一次
但是当我喜欢这个的时候
(println "T2 transfer")
(Thread/sleep 5000)
(send-off trx-agent println "T2 transfer")
它根本不打印T2传输
消息。问题是什么?您使用的关机代理太快了
(defn transfer [from to amount]
(println :transfer-enter amount)
(alter
(.balance from) - amount)
(alter
(.balance from) + amount)
(println :transfer-exit amount)
)
(defrecord Account [balance])
(def account1 (Account. (ref 100)))
(def account2 (Account. (ref 100)))
(def trx-agent (agent 0))
(defn -main [& args]
(println :main-enter )
(future
(dosync
(println :t2-enter)
(send-off trx-agent println "agent: T2 transfer")
(Thread/sleep 500)
(transfer account1 account2 20)
(println :t2-exit)
))
(dosync
(println :t1-enter)
(send-off trx-agent println "agent: T1 transfer")
(transfer account1 account2 10)
(println :t1-exit))
(Thread/sleep 2000)
(shutdown-agents)
(println :main-exit )
)
结果:
:main-enter
:t2-enter
:t1-enter
:transfer-enter 10
:transfer-exit 10
:t1-exit
0 agent: T1 transfer
:transfer-enter 20
:t2-enter
:transfer-enter 20
:transfer-exit 20
:t2-exit
nil agent: T2 transfer
:main-exit
所以T2现在只等待500毫秒,而T1立即运行。我们在调用关闭代理之前等待2000毫秒,这将杀死阻止代理运行的所有代理线程。我发现您的代码片段至少有三个错误:
您的传输
功能
(defn transfer [from to amount]
(alter
(.balance from) - amount) ;; <======== from - amount
(alter
(.balance from) + amount)) ;; <======== from + amount
表示您正在将代理的状态设置为
(println state-of-agent "T2 transfer")`
它是nil
,因为println
总是返回nil
。我不这么认为
这就是你想要的
您的transfer
函数中有一个竞争条件。由于您没有将从
和原子化修改为
,因此有可能发生竞争
但当我在事务内部调用transfer
时,它在任何情况下都应该是原子的,不是吗?我只想显示消息。有没有办法避免显示状态?>但当我在事务内部调用transfer时,它在任何情况下都应该是原子的,不是吗?是的,没错。但是传输的正确性取决于调用它的“方式”,这不是一个好的属性。老实说,我真的不明白你的代码的全部目的。你到底想打印什么?一般来说,我使用函数transfer
的唯一原因是为了以后从其他代码中显示出来哈哈。一般来说,除了测试或演示目的之外,没有其他目的。哦,我明白了。基本上,在调用println transfer
之前,我会等待10秒(事务重试),但在提交时,代理会关闭