3

重複したイベントを処理しようとしています (MIDI ノートオン信号とノートオフ信号が 3 重になります)。イベントが(ほぼ)同時に発生しない限り、エージェントを使用してロックが機能するようです。

次に例を示します。

(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

ロックをオンにする時間がないように見えるため、エージェントは複数の先物で増加します。

ここで、重複した同時イベントに対処しないようにするための何かが欠けていることを願っています。

ありがとう!

4

1 に答える 1

2

エージェントは非同期で調整されていないため、エージェントにメッセージを送信してから、送信されたアクションが実際に実行されるまでに遅延が生じる場合があります。この遅延の間(send test-val + 1)、最初の呼び出しが実際に実行されて @allow-update が false に設定される前に、ほとんどまたはすべての呼び出しがロックされたセクションを通過する可能性があります。これは、test-val の状態が変更される前に先頭の 0 で確認できます。

アトムはロックとのやり取りに適しているかもしれませんが、refs は複数の ID への調整されたアクセスのための適切なツールかもしれません。

于 2013-03-29T00:05:14.480 に答える