【问题标题】:Handling simultaneous duplicate events in Clojure在 Clojure 中处理同时发生的重复事件
【发布时间】:2013-03-28 23:32:58
【问题描述】:

我正在尝试处理重复事件(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))))

如果我在对 increase-val 的调用之间稍有延迟进行测试:

(run-futures 2)
;outputs 0111111111111111111 every time, as expected

但如果我让所有对 increase-val 的调用同时发生:

(run-futures 0)
;001222222222222222
(run-futures 0)
;000000145555555555
(run-futures 0)
;000000013677777777

似乎锁没有时间打开,所以代理增加了多个期货。

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

谢谢!

【问题讨论】:

  • 能否包含 test-val 的定义?我假设它是一个代理?

标签: concurrency clojure event-handling


【解决方案1】:

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

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

【讨论】:

  • 做到了。我对 atom 和 vars 也有同样的问题,但我忘了尝试 refs。谢谢!
猜你喜欢
  • 2023-03-26
  • 1970-01-01
  • 2019-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多