在浏览器中,JavaScript是否可能发生并发读/写-读/写冲突?

6
我有一个这样的情况:我正在进行几个(比如四个)ajax调用(使用AngularJS http get,如果那很重要),我希望每个调用都回调并递增一个计数器,以便我知道所有(四个)线程何时完成。
我的担忧是,由于JavaScript没有任何可与Java的“同步”或“易失性”关键字相媲美的东西,因此可能会发生多个并发线程在递增计数器时发生冲突,从而错过一些递增。
换句话说,两个线程同时到达,都读取计数器,获得相同的值(例如100)。然后两个线程都将计数器递增(到101),并存储新值,结果我们错过了一次计数(变成了101而不是102)!
我知道JavaScript应该是单线程的,但也有例外。
在浏览器中是否可能出现这种情况?如果是这样,有什么方法可以防止它发生吗?

3
由于Promises的存在,不需要计数器。请查看$q.all()$http返回一个Promise,您可以包装一组Promise,并在它们全部完成时调用done。 - charlietfl
这种情况我从未遇到过,就我所知,但我正在等待答案!好问题! - shaheer
1
@mplungjan 那会非常慢。 - shaheer
@mplungjab,你的方法太慢了;为什么每次调用都要等待上一个之后才能继续呢?我想知道你的解决方案是否必要,或者JavaScript是否已经为我们处理好了。 - Victor Grazi
@VictorGrazi,除非调用彼此传递数据,否则这绝不是常见的方法。 - charlietfl
显示剩余2条评论
2个回答

5
不可能发生冲突,因为每个 AJAX 调用的响应都可以看作是 JavaScript 消息队列上的一条消息。JavaScript 运行时会处理队列上的每个消息直到完成,然后再处理下一个消息。换句话说,在移动到队列中的下一条消息之前,它会调用事件的回调函数并运行完整个回调函数(以及所有它所调用的函数等等)。因此,没有两条消息(例如 AJAX 响应)会并行处理。
来源:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop 同时,我在 JavaScript 上工作了多年,可以保证这就是它的工作方式。

我相信你,但你能否提供一些解释或证明你的说法的来源? - Victor Grazi

3

就像您提到的那样,由于JavaScript是单线程的,我认为不会发生这种情况。只有在使用webworkers时,JS才会变成多线程,但即使如此,它们也不共享相同的变量(它们克隆您传递的js属性对象,我在这里假设),因此不应该出现读/写重叠的情况。

编辑

仔细考虑后,假设有一个名为onCounterIncreament的函数,当计数器增加时会执行一堆操作。如果您不在增加计数器后立即调用它,而是使用$watch或一些超时函数来检查计数器的变化,很可能会错过一个改变。


我的理解是单线程的规则有例外。例如,如果多个ajax调用同时返回,或者像鼠标事件等需要并发以确保活力的情况下,就需要使用并发处理。 - Victor Grazi
@VictorGrazi,“JavaScript可能是异步的,这是真的。但是没有WebWorkers的基本JavaScript永远不会是多线程的。请参阅Már Örlygsson的答案”——https://dev59.com/BHE85IYBdhLWcg3whT9r - mido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接