两个异步任务可以同时访问同一阵列吗?

时间:2018-09-02 12:38:05

标签: javascript typescript asynchronous

假设您有一个被一个异步进程修改过的数组,然后又有另一个异步进程从同一数组中读取数据。修改和读取是同步完成的。现在的问题是,在写入过程修改数组时,读取过程可以以某种方式获得对数组的访问吗?

根据经验,我知道它不能,并且在进行同步操作时,线程将因此被阻塞,因此所有在其上运行的资源(包括数组)都将被阻塞。对?但是从逻辑上讲,JavaScript是单线程的还是在规范中特别概述了它?

2 个答案:

答案 0 :(得分:5)

  

现在的问题是,在写入过程修改数组时,读取过程可以以某种方式获得对数组的访问吗?

否,JavaScript是单线程的。通过JS同时访问相同数据的唯一方法是在两个不同JS脚本之间使用一些共享资源。在可以是带有SharedArrayBuffers的WebWorkers的Web上,在Nodejs上,某些数据库允许并发突变。

  

但是从逻辑上讲,JavaScript是单线程的还是在规范中特别概述了它?

规范确实定义了称为代理的线程:

  

8.3个代理商

     

代理包括一组ECMAScript执行上下文,一个执行上下文堆栈,一个正在运行的执行上下文,一个   一组命名作业队列,一个代理记录和一个执行线程。除执行线程外,   完全属于该代理商的代理商

这意味着所有代码都在同一线程(作业队列)上运行,所有变量只能从一个线程(执行上下文)访问。在不同的代理程序(线程)之间共享内存的唯一方法是使用SharedArrayBuffer,并且您需要不同的代理程序(例如Webworkers)。

答案 1 :(得分:1)

我会做的一种方法是制作3个数组。

 let kingArray = [];
 let arrayForProcess1 = [];
 let arrayForProcess2 = [];

 someProcessOneExecution().then(response => {
    if (kingArray.length === 0) {
       arrayForProcess1 = response;
    } else {
       doSomethingWithResponse(response);
    }
 });

 someProcessTwoExecution().then(response => {
    if (kingArray.length === 0) {
       arrayForProcess2 = response;
    } else {
       doSomethingWithResponse(response);
    }
 });

 function doSomethingWithResponse() {
    // so something here..
 }

这与您要求的不完全相同,但是javascript事件循环或调用堆栈将逐个执行它们。由于JS是单线程的。由于它们是I / O的基础,并且随着它们的解决,它将等待这些承诺解决。可以为process1process2。您可以像上面的方法中那样,手动检查它们,这不是最佳方法。

第二种方法

在这种情况下,我要做的一件事就是将这两个诺言链接在一起,然后等待它们一个接一个地解决并相应地更新我的数组。

我个人的观点(2美分的观点),我永远不会尝试同时更新同一阵列,如果在这种情况下是用例,则可能需要重新考虑问题执行策略。