在Node.js中按顺序递增计数器。

huangapple go评论65阅读模式
英文:

Increment counter sequentially in Node.js

问题

我想知道如何确保在Node.js环境中正确递增计数器。

如果我理解正确,异步函数是由4个libuv库线程实例化的非主线程处理的,回调函数由主线程(事件循环)执行。

如果上面的说法正确,那么下面的代码可能会导致计数器的不正确更新,因为f1()f2()可能同时尝试更新counter,最终结果为1而不是2

我如何重写以下代码以确保正确更新计数器?

var counter = 0

async function f1() {
  // 做一些操作

  counter++
}

async function f2() {
  // 做一些操作

  counter++
}
f1()
f2()
英文:

I want to know how can I ensure that I increment counter correctly in Node.js environment.

If I understand correctly, async functions are processed by non-main threads that are instantiated by 4 libuv library threads, and the callbacks are executed by the main thread (event loop).

If above is true, then below code can result in incorrect updates to counter because f1() & f2() can try to update counter at the same time giving a final result of 1 instead of 2.

How do I rewrite the code below to ensure correct update to counter?

var counter = 0

async function f1() {
  // do something
  
  counter++
}

async function f2() {
  // do something
  
  counter++
}
f1()
f2()

答案1

得分: 2

没有,f1f2 没有办法同时访问相同的 counter 变量,因此“最终”结果将是2。但是哪个函数是 f1f2 设置为 12 是不确定的。

异步函数仍然由唯一的 JavaScript 处理运行,而不是由后台线程运行。也许它们自己会等待一些由其他进程处理的任务,这取决于它们将进行的 API 调用,但是 JavaScript 部分仍然由唯一的 JavaScript 处理运行,可以访问 counter 变量。

因此,在这里没有冲突的风险。

唯一可能出现此类问题的情况是在不同的 JavaScript 上下文之间共享 SharedArrayBuffer 对象时(例如,使用 web workers)。但是对于这种情况,我们有 Atomics。但是在这里,counter 变量不是 SharedArrayBuffer,不能在不同上下文之间共享。因此,再次强调,当 f1f2 都以不确定的顺序解决时,counter 将保持值为 2

英文:

No, there is no way that f1 and f2 do access the same counter variable at the same time, so the "final" result will be 2.
However which of f1 or f2 would have set it to 1 or 2 is unsure.

Async functions are still ran by the one and only JS processing, not by background threads. Maybe they will themselves be waiting for some tasks that are processed by other processes, depending on the API calls they'll make, but the JS part is still ran by the one and only JS processing that has access to the counter variable.

So there is no risk of clashing here.

The only case where you could have such an issue is with SharedArrayBuffer objects, when shared across different JS contexts (e.g with web workers). Though for this case we have Atomics.
But here the counter variable is not a SharedArrayBuffer, and can't be shared across contexts. So once again, when f1 and f2 will both have resolved in an undetermined order, counter will hold the value 2.

答案2

得分: 0

如果我理解正确,异步函数是由非主线程处理的。

这是不正确的。所有异步函数都在主线程中处理。因此,调用 f1()f2() 将始终导致计数器增加两次。它永远不会失败。这是因为 JavaScript 是单线程的。

重要的是要知道 JavaScript 是单线程的。即使是在 Node.js 中由多个线程执行的操作,例如调用 Web Workers 或执行文件 I/O,也会通过事件循环串行化回到主线程。

除非您使用非标准的第三方线程库,否则在 Node.js 中变量访问永远不会同时发生。这是因为在 Node.js 中无法在工作线程之间共享变量(也就是说,如果您使用 worker_threads - 在正常编码中,您甚至不会在单独的线程中执行自己的代码)。数据通过消息在线程之间交换 - 类似于互联网上的客户端和服务器共享数据的方式:它们永远不会访问彼此的变量。

英文:

> If I understand correctly, async functions are processed by non-main threads

This is not true. All async functions are processed in the main thread. Therefore calling f1() and f2() will always result in counter being incremented twice. It will never fail. This is because javascript is single threaded.

It is important to know that javascript is single threaded. Even operations that are performed in multiple threads by Node.js such as calling web workers or performing file I/O are serialized back to the main thread by the event loop.

Unless you're using non-standard 3rd party threading libraries variable access in node.js are never simultaneous. This is because variables cannot be shared between workers in node.js (that is, if you use worker_threads - in normal coding you're not even executing your own code in separate threads). Data is exchanged between threads via messages - similar to the way client and servers on the internet share data with each other: they never access each other's variables.

huangapple
  • 本文由 发表于 2023年6月25日 20:59:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76550521.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定