具有复合赋值的JavaScript中的竞争条件 [英] Race condition in JavaScript with compound assignment
问题描述
我不是在谈论复杂的比赛条件涉及网络或事件.相反,我似乎发现+=
运算符在V8(Chrome 58或Node 8)中不是原子的.
I'm not talking about complex race conditions involving the network or events. Rather, I seem to have found out that the +=
operator is not atomic in V8 (Chrome 58, or Node 8).
下面的代码旨在并行运行两个所谓的线程.每个线程"重复调用一个函数,该函数在之后返回其number参数.睡觉那么多秒.结果是总结到蓄能器.
The code below aims to run two so-called threads in parallel. Each "thread" calls repeatedly a function that returns its number parameter after sleeping that many seconds. The results are summed up into an accumulator.
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Return the passed number after sleeping that many seconds
async function n(c) {
await sleep(c * 1000);
console.log('End', c);
return c;
}
let acc = 0; // global
// Call n repeatedly and sum up results
async function nForever(c) {
while (1) {
console.log('Calling', c);
acc += await n(c); // += not atomic?!
console.log('Acc', acc);
}
}
(async function() {
// parallel repeated calls
nForever(1);
nForever(5.3); // .3 for sanity, to avoid overlap with 1 * 5
})();
问题在于,〜5秒后,我希望累加器为10.3(5乘以1 + 5.3乘以1).但是,它是5.3!
The problem is that after ~5 seconds, I'd expect the accumulator to be 10.3 (5 times 1 + 1 times 5.3). However, it's 5.3!
推荐答案
这不是竞争条件,因为您明确地使用await
产生执行.
This is not a race condition, because you are explicitly yielding the execution using await
.
该标准定义诸如+=
之类的复合赋值不是原子的:复合赋值的左侧在右侧之前进行评估. [
The standard defines that a compound assignment such as +=
is not atomic: The left-hand-side of a compound assignment is evaluated before the right-hand-side.[1]
因此,如果您的RHS以某种方式更改acc
,则更改将被覆盖.最简单的例子:
So if your RHS changes acc
somehow, the changes will be overwritten. Most simple example:
var n = 1;
n += (function () {
n = 2;
return 0;
})();
console.log(n);
这篇关于具有复合赋值的JavaScript中的竞争条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!