gpt4 book ai didi

javascript - 从异步函数对同一对象的并发写入访问是否会导致无效值?

转载 作者:行者123 更新时间:2023-12-01 00:01:10 24 4
gpt4 key购买 nike

我想知道以下代码是否会导致对象context中的整数i具有无效值。到目前为止,我的实验还没有出现问题。

// Node.js (v10.19.0)

const Promise = require('promise')

// object accessed from different async processes in parallel
let context = {i: 0}

// create async functions
let funkMaker = function(i) {
return async function(context) {
context.i += 1;
console.log(`Funk${i} at ${Date.now()}: Incremented argument 'context.i' to: ${context.i}`);
return context.i
}
}

// create async processes
let funksArr = [];
for (k=1; k<101; k++) {
funksArr.push(funkMaker(k))
}

// invoke async processes in parallel
Promise.all(
funksArr.map(f => f(context))
).then(
x => console.log(`Promise.all resolved with ${x}`)
).catch(
e => console.log(`Promise.all raised an error:\n${e}`)
)

上面产生以下输出(摘录):

Funk1 at 1584448782621: Incremented argument 'context.i' to: 1   
Funk2 at 1584448782621: Incremented argument 'context.i' to: 2
Funk3 at 1584448782622: Incremented argument 'context.i' to: 3
Funk4 at 1584448782622: Incremented argument 'context.i' to: 4
Funk5 at 1584448782622: Incremented argument 'context.i' to: 5
Funk6 at 1584448782622: Incremented argument 'context.i' to: 6
Funk7 at 1584448782622: Incremented argument 'context.i' to: 7
Funk8 at 1584448782622: Incremented argument 'context.i' to: 8
Funk9 at 1584448782622: Incremented argument 'context.i' to: 9

正如您所看到的,有几个进程似乎在同一毫秒内访问 context.i(上面的 Funk3Funk9 )。我很困惑为什么整数 context.i 仍然正确递增并且没有错误。

欢迎提出见解。谢谢!

更新

为了在真正的系统线程中尝试这一点,我调整了从 this blog post 窃取的代码。它使用crypto和隐式libuv在真实线程中执行。我仍然无法让我的 context.i 崩溃。老实说,我仍然感到困惑。

const crypto = require("crypto");
const start = Date.now();

let context = {i: 0}

function logHashTime(context) {
crypto.pbkdf2("a", "b", 100000, 512, "sha512", () => {
context.i += 1;
console.log(`Hash: ${Date.now() - start}, 'context.i' incremented to: ${context.i}`);
});
}

for (i = 0; i < 100; i++) {
logHashTime(context)
}

输出(摘录)仍然“很好”:

Hash: 1268, 'context.i' incremented to: 1  
Hash: 1460, 'context.i' incremented to: 2
Hash: 1660, 'context.i' incremented to: 3
Hash: 1907, 'context.i' incremented to: 4
Hash: 2493, 'context.i' incremented to: 5
Hash: 2673, 'context.i' incremented to: 6
Hash: 3154, 'context.i' incremented to: 7
Hash: 3215, 'context.i' incremented to: 8
Hash: 3662, 'context.i' incremented to: 9

最佳答案

首先,这里没有实际的异步代码。虽然您的函数被声明为异步,但它的函数体仍然同步执行,并且该函数体中没有实际的异步操作。事实上,它被标记为 async 意味着它返回一个 promise ,但这就是您的示例中的所有更改。

其次,Javascript 在单个线程中运行 Javascript,除非您明确使用工作线程(您没有在那里使用)。

因此,由于一切都是同步的并且都在单个线程中运行,因此代码只会按照 .map() 循环运行的顺序可靠地运行。这里唯一真正异步的是当 async 函数返回的 Promise 调用其 .then() 处理程序时,该处理程序允许 Promise.all() 调用其 .then() 处理程序。但是,所有结果在此之前都是同步生成的。

As you can see there are several processes that appear to be accessing context.i at the very same millisecond (Funk3 to Funk9 above). I am puzzled as to why the integer context.i still gets incremented correctly and without an error.

它们都按顺序一次运行一个。您看到相同的毫秒只是因为您没有足够的计时器分辨率来实际看到执行时间的差异。这些功能实际上都没有“同时”运行。

context.i 会正确递增,因为这些函数实际上是按顺序依次调用和运行的。

关于javascript - 从异步函数对同一对象的并发写入访问是否会导致无效值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60722673/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com