【问题标题】:Can two asynchronous tasks access the same array at the same time?两个异步任务可以同时访问同一个数组吗?
【发布时间】:2019-02-07 18:20:38
【问题描述】:

假设您有一个由一个异步进程修改的数组,然后您有另一个从同一数组读取的异步进程。修改和读取是同步完成的。现在的问题是,读进程能否在写进程修改数组时以某种方式获得对数组的访问权限?

根据经验,我知道它不能,并且当同步操作正在进行时,线程因此它所操作的所有资源(包括数组)都将被阻塞。正确的?但是,这是因为 JavaScript 是单线程的,还是在规范中的某个地方专门列出了这一事实,这在逻辑上是必然的结果吗?

【问题讨论】:

  • Javascript 在单线程上执行,我建议你阅读一下异步操作在 javascript 中的工作原理。
  • 您有具体问题还是只是一般问题?如果你有一个特定的问题应该概述这是什么
  • 据我所知,worker 的后台线程处于提案或测试阶段。就像共享工作者或网络工作者一样。但是目前对于您的问题,Nodejs 是单线程的,我认为即使使用依赖注入,您也不能从不同的进程共享相同的变量访问。使用 IPC 将更改传达给主进程和子进程以进行数据共享。
  • 您可以使用 redis 之类的东西跨进程共享变量,这是一种可行且经常使用的解决方案

标签: javascript typescript asynchronous


【解决方案1】:

现在的问题是,读取进程能否在写入进程修改数组时以某种方式获得对数组的访问权限?

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

但这是否是由于 JavaScript 是单线程的,还是在规范中的某个地方特别列出的事实?

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

8.3 代理

一个代理由一组 ECMAScript 执行上下文、一个执行上下文堆栈、一个运行执行上下文、一个 一组命名作业队列、一个代理记录和一个执行线程。除了执行线程, 代理专属于该代理

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

【讨论】:

  • Afaik Atomics do 定义了一个线程模型,但是是的,其余的应该是单线程的。
  • 原子似乎很有趣,(y) 我不知道它们。
  • @bergi 什么是代理?我刚刚在规格中发现它看起来可能是相关的
  • @JonasWilms 我猜是线程的概括(但我自己还没有阅读规范)
  • 有趣的是,我没有注意到 MDN 页面上提到了它。
【解决方案2】:

我会做的一种方法是制作 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 是单线程的。它将等待这些 Promise 解决,因为它们是 I/O 基础并且它们得到解决。可以是process1process2。您可以像上面的方法一样手动检查它们,这不是最佳方法。

第二种方法

在这种情况下,我会做的一件事是将这 2 个 Promise 链接在一起,并等待它们被一一解决并相应地更新我的数组。

我自己的个人意见(2 美分意见)我永远不会尝试同时更新同一个数组,如果这是这种情况下的用例,可能需要重新考虑问题执行策略。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 2012-08-19
    相关资源
    最近更新 更多