交换!原子中的值(嵌套映射)Clojure

时间:2017-04-17 16:39:36

标签: multithreading concurrency clojure

我试图从多个线程更新原子(地图)中的嵌套计数器,但会得到不可预测的结果。

var sources = [];

function scheduler(audioStart, index) {
    audio = context.createBufferSource();
    sources[index] = audio; 
    audio.buffer = audioSamples[index];  //array with all the loaded audio
    audio.connect(context.destination);  
    audio.start(audioStart + (audio.buffer.duration * index));
}

function stopAll() {
    for(let i = 0; i < 8; i++)
        if (sources[i])
          sources[i].stop(0);
}

我是Clojure的新手,所以我很可能做错了什么,但却无法弄清楚是什么。它打印一个计数器值,结果从4-10变化,每次不同。

我想以原子方式更新计数器值,并希望这种方法总能给出10的计数器值。它只会在失败时重试并最终达到10。

可以同时触发的向上投票功能。

你能看到我在这里做错了吗?

1 个答案:

答案 0 :(得分:5)

您正在代码中非原子地更新原子。您首先通过@a获取其值,然后使用swap函数应用它。值可能会在两者之间发生变化。

更新值的原子方法是在swap中使用纯函数,而不通过@引用前一个原子值:

(defn upvote [id]
  (swap! a update-in [(keyword id) :counter] inc))