我在交易中尝试send-off
函数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)
它会在事务重试时显示两次消息。所以我决定使用agents
使副作用操作println
只运行一次。
但是当我喜欢这个时
(send-off trx-agent println "T2 transfer")
根本不打印T2 transfer
条消息。有什么问题?
答案 0 :(得分:1)
您过早使用shutdown-agents
。
(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立即运行。我们在调用shutdown-agents
之前等待2000毫秒,这会杀死阻止代理运行的所有代理线程。
答案 1 :(得分:1)
我发现您的代码片段至少有三个问题:
您的transfer
功能
(defn transfer [from to amount]
(alter
(.balance from) - amount) ;; <======== from - amount
(alter
(.balance from) + amount)) ;; <======== from + amount
看起来你真的想说改变from
然后改变to
来自send-off
文档:
向代理发送可能阻止的操作。返回代理 立即。随后,在一个单独的线程中,状态 agent将设置为以下值:(应用action-fn state-of-agent 参数)
所以我认为你不需要那个未来。这一行
(send-off trx-agent println "T2 transfer")
表示您将代理的状态设置为
的结果(println state-of-agent "T2 transfer")`
,nil
,因为println
始终返回nil
。我不认为
这就是你想要的。
您transfer
函数中存在竞争条件。由于您没有原子地修改from
和to
,因此可能会在那里进行比赛。