异步函数对同一对象的并发写访问会导致无效值吗?

我想知道以下代码是否会导致对象i中的整数context具有无效值。到目前为止,我无法在实验中引起任何问题。

// 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.iFunk3)访问Funk9。我对为什么整数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
wxh19871203 回答:异步函数对同一对象的并发写访问会导致无效值吗?

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

第二,除非您显式使用工作线程(您在那里没有使用过工作线程),否则Javascript在单个线程中运行Javascript。

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

正如您所看到的,在同一毫秒(上面的Funk3至Funk9)似乎有多个进程正在访问context.i。我对为什么整数context.i仍然可以正确递增且没有错误感到困惑。

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

context.i正确地增加了,因为这些函数实际上已被调用并依次依次运行。

本文链接:https://www.f2er.com/2632384.html

大家都在问