浏览器中的 JavaScript 中是否存在并发读/写读/写冲突

Is it possible for a concurrent read/write read/write collision in JavaScript in the browser?

本文关键字:写读 冲突 存在 JavaScript 是否 浏览器 并发      更新时间:2023-09-26

我有一个情况,我正在进行几个(比如四个)ajax调用(使用AngularJS http get,如果这很重要的话),我希望每个调用都回调并增加一个计数器,这样我就可以知道所有(四个)线程何时完成。

我担心的是,由于JavaScript没有任何可与Java的"同步"或"易失性"关键字相媲美的东西,因此在增加计数器时,多个并发线程可能会发生冲突,从而错过一些增量。

换句话说,两个线程同时出现,并且都读取计数器,获得相同的值(例如 100)。然后两个线程都递增该计数器(到 101)并存储新值,看哪,我们错过了一个计数(101 而不是 102)!

我知道JavaScript应该是单线程的,但也有例外。

这种情况在浏览器中是否可能,如果是,有什么方法可以防止它吗?

不,这是不可能的(不会发生冲突)。每个 AJAX 调用响应都可以被视为 JavaScript 消息队列上的一条消息。JavaScript 运行时先处理队列上的每条消息,直到完成,然后再处理下一条消息。换句话说,它调用事件的回调,并在移动到队列中的下一条消息之前运行完整的回调函数(以及它调用的所有函数,依此类推)直到完成。因此,不会并行处理两条消息(例如,AJAX 响应)。

资料来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop

另外,我已经在JavaScript上工作了很多年,可以保证这就是它的工作方式。

就像你提到的,由于javascript是单线程的,我认为这样的场景不会发生,js变成多线程的唯一方法是当你使用webworkers时,但即使它们不共享相同的变量(它们克隆你传递的属性js对象,我在这里假设),所以应该有任何读/写重叠的情况

编辑

再三考虑,假设有一个函数onCounterIncreament它会在计数器增量时执行一堆操作,如果你在输入计数器后不立即调用它,而是使用$watch或其他超时 fn 来检查计数器的变化,很有可能你可能会错过变化。