Concurrency 在Clojure中处理同时发生的重复事件

Concurrency 在Clojure中处理同时发生的重复事件,concurrency,clojure,event-handling,Concurrency,Clojure,Event Handling,我试图处理重复事件(MIDI音符打开和音符关闭信号一式三份)。似乎使用代理和锁定是可行的,除非事件(几乎)同时发生 下面是一个例子: (def test-val (agent 0)) (def allow-update (agent true)) (defn increase-val [] (locking allow-update (when @allow-update (send allow-update (fn [_ x] x) false) (se

我试图处理重复事件(MIDI音符打开和音符关闭信号一式三份)。似乎使用代理和锁定是可行的,除非事件(几乎)同时发生

下面是一个例子:

(def test-val (agent 0))
(def allow-update (agent true))

(defn increase-val []
  (locking allow-update
    (when @allow-update 
      (send allow-update (fn [_ x] x) false)
      (send test-val + 1)))
  (print @test-val))

(defn run-futures [delay-time]
  (send allow-update  (fn [_ x] x) true)
  (send test-val * 0)
  (dotimes [_ 20] 
    (Thread/sleep delay-time)
    (future (increase-val))))
如果我在两次调用之间稍微延迟以增加val来测试它:

(run-futures 2)
;outputs 0111111111111111111 every time, as expected
但如果我让所有增加val的调用同时发生:

(run-futures 0)
;001222222222222222
(run-futures 0)
;000000145555555555
(run-futures 0)
;000000013677777777
似乎锁没有时间打开,所以代理增加了多个期货

我希望我在这里遗漏了一些东西,可以确保我不会对重复的同时发生的事件采取行动

谢谢

由于代理是异步且不协调的,因此在您向它们发送消息和实际运行所发送的操作之间可能存在延迟。在此延迟期间 对
(send test val+1)
的大多数或所有调用都可能在第一个调用实际运行并将@allow update设置为false之前通过锁定部分。在test val的状态更改之前,您可以在前面的0中看到这一点


原子可能更适合与锁交互,尽管REF可能是协调访问多个身份的正确工具

您能介绍一下测试val的定义吗?我猜是个探员?是他干的。我对原子和变量也有同样的问题,但我忘了尝试参考。谢谢