clojure sendoff 打印函数
clojure sendoff println function
我正在尝试 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
消息。有什么问题?
您使用 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 毫秒,这将杀死所有代理线程以阻止代理 运行.
我发现您的代码片段至少有三处错误:
你的 transfer
函数
(defn transfer [from to amount]
(alter
(.balance from) - amount) ;; <======== from - amount
(alter
(.balance from) + amount)) ;; <======== from + amount
看起来你真的想说 alter from
然后 alter to
来自 send-off
文档:
Dispatch a potentially blocking action to an agent. Returns the agent
immediately. Subsequently, in a separate thread, the state of the
agent will be set to the value of: (apply action-fn state-of-agent
args)
所以我认为你不需要那个未来。还有行
(send-off trx-agent println "T2 transfer")
表示您正在将代理的状态设置为
的结果
(println state-of-agent "T2 transfer")`
即 nil
,因为 println
总是 returns nil
。我不认为
这就是你想要的。
您的 transfer
函数中存在竞争条件。由于您没有以原子方式修改 from
和 to
,因此那里有可能发生竞争。
我正在尝试 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
消息。有什么问题?
您使用 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 毫秒,这将杀死所有代理线程以阻止代理 运行.
我发现您的代码片段至少有三处错误:
你的
transfer
函数(defn transfer [from to amount] (alter (.balance from) - amount) ;; <======== from - amount (alter (.balance from) + amount)) ;; <======== from + amount
看起来你真的想说 alter
from
然后 alterto
来自
send-off
文档:Dispatch a potentially blocking action to an agent. Returns the agent immediately. Subsequently, in a separate thread, the state of the agent will be set to the value of: (apply action-fn state-of-agent args)
所以我认为你不需要那个未来。还有行
(send-off trx-agent println "T2 transfer")
表示您正在将代理的状态设置为
的结果(println state-of-agent "T2 transfer")`
即
nil
,因为println
总是 returnsnil
。我不认为 这就是你想要的。您的
transfer
函数中存在竞争条件。由于您没有以原子方式修改from
和to
,因此那里有可能发生竞争。