title: Race condition in JavaScript with compound assignment
body: <p>I'm not talking about complex race conditions <a href="https://stackoverflow.com/questions/338110/avoiding-a-javascript-race-condition">involving the network</a> or <a href="https://stackoverflow.com/questions/7238586/do-i-need-to-be-concerned-with-race-conditions-with-asynchronous-javascript">events</a>. Rather, I seem to have found out that the <code>+=</code> operator is not atomic in V8 (Chrome 58, or Node 8).</p>
  
  <p>The code below aims to run two so-called threads in parallel. Each "thread" calls repeatedly a function that returns its number parameter after <a href="https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep/39914235#39914235">sleeping</a> that many seconds. The results are <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Assignment_Operators#Addition_assignment" rel="noreferrer">summed up</a> into an accumulator.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>function sleep(ms) {
    return new Promise(resolve =&gt; 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
  })();</code></pre>
  </div>
  </div>
  </p>
  
  <p>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!</p>
  
  <p><a href="https://i.stack.imgur.com/BNPAA.png" rel="noreferrer"><img src="https://i.stack.imgur.com/BNPAA.png" alt="+= not atomic"></a></p>