Javascript 如何并行运行两个setTimeout任务?

Javascript 如何并行运行两个setTimeout任务?,javascript,parallel-processing,mutable,Javascript,Parallel Processing,Mutable,我正在阅读本文,并且在前面我们讨论了异步、并行和并发代码之间的区别 我有一个简单的异步示例: let output = 0; const bar = (cb) => setTimeout(cb, Math.random() * 1000); const foo = (cb) => setTimeout(cb, Math.random() * 1000); bar( () => { output = 1; }); foo( () => { output =

我正在阅读本文,并且在前面我们讨论了异步、并行和并发代码之间的区别

我有一个简单的异步示例:

let output = 0;
const bar = (cb) => setTimeout(cb, Math.random() * 1000);
const foo = (cb) => setTimeout(cb, Math.random() * 1000);

bar( () => {
    output = 1;
});
foo( () => {
    output = 2
});
setTimeout(() => {
    // This Async code should have 2 different outputs
    output;
}, 2000);
基于Math.random计时器和可变输出,上述代码可以有两个答案:

不过,我想增加一点复杂性,并将foo和bar转换为并行运行。。。我不太了解如何实现这一点:

问题:我们如何更新下面的代码,使
bar
foo
并行运行,从而使输出具有两种以上的可能结果

注意:这纯粹是为了学习的目的。。。我想看看比赛情况如何

let inputA = 10;
let inputB = 11;

const bar = (cb) => setTimeout(cb, Math.random() * 1000);
const foo = (cb) => setTimeout(cb, Math.random() * 1000);


bar( () => {
    inputA++;
    inputB = inputB * inputA;
    inputA = inputA + 3;
});
foo( () => {
    inputB--;
    inputA = 8 + inputB;
    inputB =  inputA * 2;
});
setTimeout(() => {
    // This Parallel code should have more than 2 outputs;
    console.log(inputA, inputB);
}, 2000);

对于最初的问题,您希望看到它们并行运行。您可以使用Promise.all运行多个异步任务,它将等待所有异步任务的解决并返回一个输出数组

all通过迭代异步任务(串联)来执行异步任务,从技术上讲,不是并行执行,而是并行运行。当所有异步任务都已解决或其中任何一个失败时被拒绝时,它将为您提供一个结果

或者你可以不做任何承诺,一个接一个地运行它们。它们不会互相阻塞,所以仍然是并行的,但您保证。所有这些都只会帮助您在一个地方处理回调结果

根据您为bar和foo函数设置的随机超时,输出将为12或20

对于竞争条件,只有setTimeout函数是异步的,但是回调中的所有操作都是同步的和非阻塞的,因此线程不会从一个回调中的操作跳到另一个回调中,除非该回调中的所有操作都已完成

但在JS中,当使用SharedArrayBuffer时,您仍然可以进行数据竞争,而SharedArrayBuffer需要对象来防止数据竞争

let输出=0;
设输入=10;
设inputB=11;
常数条=(cb)=>setTimeout(cb,Math.random()*1000);
constfoo=(cb)=>setTimeout(cb,Math.random()*1000);
条(()=>{
输入++;
inputB=inputA;
输出=输入+1;
});
foo(()=>{
输入b-;
inputA=inputB;
输出=输入B*2;
});
Promise.all([bar(),foo()]))
.then(output=>console.log('foo和bar任务使用output'完成),output));
设置超时(()=>{
console.log('输出变量值:',输出)

}, 2000);幸运的是,您希望调用的竞争条件在普通Javascript中是不可能的。任何时候,当您有一个同步函数时,一旦控制流被传递给该函数,该函数绝对保证在环境中的任何其他Javascript运行之前运行到底(或抛出)

例如,给定1000个由
setTimeout
计划在未来1-2秒内(随机)发生的任务,并且您还可以在1.5秒后调用以下函数:

const fn = () => {
  console.log('1');
  for (let i = 0; i < 1e8; i++) {
  }
  console.log('2');
};
const fn=()=>{
console.log('1');
for(设i=0;i<1e8;i++){
}
console.log('2');
};
一旦
fn
启动,它将在下一个随机函数运行之前(同步)运行其所有代码。因此,即使随机函数调用
console.log
,仍然可以保证在上述情况下,
2
将在
1
之后立即被记录

因此,在您最初的示例中,只有两种可能性:

  • bar
    的回调首先运行并完全完成,然后
    foo
    的回调运行并完全完成。或:
  • foo
    的回调首先运行并完全完成,然后
    bar
    的回调运行并完全完成

即使随机超时落在完全相同的数字上,也不可能发生其他情况。在任何给定的时间,控制流只能在代码中的一个位置。

推送到数组,而不是重新分配变量?我想我应该更明确地说,这纯粹是为了学习,我希望创造竞争条件。我“我更新了这个问题,希望它能更好地沟通。你的意思是,你想看看当
回调与
foo
同时运行时会发生什么,这样输入的重新分配会干扰另一个函数的运行,而不是一个函数的完成,然后另一个开始?是的,这是正确的。请添加解释。你改变了什么?你为什么变了?它如何帮助读者和解决OP的问题?这纯粹是为了学习。我希望有比赛条件。在这个例子中,我总是得到一个[4,5]的数组,它的输出是Promise.all的结果,它是bar和foo的结果。我在2s后的控制台注销中添加了一个新的输出,它是由foo和bar函数更改的输出。但是,如果共享相同数据的JS事件并行执行,那么问题将更加微妙。将这两个伪代码任务列表视为可以分别在FoE()和Bar()中运行代码的线程,并考虑如果它们在完全相同的TII上运行会发生什么,只是重读LOL,JavaScript从不跨线程共享数据,这意味着不确定性的级别是不关心的。没有真实的(完整的)吗?那么在JavaScript中的并行性呢?除非一个函数调用另一个函数,否则没有两个函数可以同时运行。尽管有web workers(以及其他主机提供的机制),由于是两个独立的环境,它们可以运行单独的JS,但这类内容超出了标准的普通JS。仅供参考,JS确实可以跨线程、代理共享一些数据。如果不确定性是一个问题,那么在JS中存在类似于竞争条件的情况。