Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
clojure发送println函数_Clojure_Stm - Fatal编程技术网

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秒(事务重试),但在提交时,代理会关闭