a)函数或b)代码行的异步性是常数吗? [英] is asynchronicity a constant for a) functions or b) lines of code?

查看:47
本文介绍了a)函数或b)代码行的异步性是常数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

join(user) {
    if(this.room.length === 2) throw new Error('The room is full');
    this.room.push(user);
};

如果异步性是基于功能的,则此代码是100%防弹的。一个房间中不可能有两个以上的用户。

If asynchronicity goes on a 'function' basis, this code is 100% bulletproof. There's no way there can be more than two users in a room.

如果异步性以每行为基础,则此代码可能会失败。为什么?因为如果三个用户同时进入房间,则可能在10毫秒的间隔内发生以下情况:

If asynchronicity goes on a 'per line' basis, this code may fail. Why? Because if three users enter the room at the same time, the following may happen in a 10ms interval:

1ms:房间为空。让用户A进入数组。

1ms: Room is empty. Let User A in, push to array.

4ms:房间有一个用户。

4ms: Room has one user.

5ms:用户B

6ms:用户C要求加入。

6ms: User C asks to join.

7ms:检查数组的长度(1 )。

7ms: Check array for length (1).

8ms:检查数组的长度(1)。

8ms: Check array for length (1).

9ms:将用户B推入数组是因为房间长度为1。

9ms: Push user B to array because room length is 1.

10ms:将用户C推送到数组,因为房间长度为1。

10ms: Push user C to array because room length is 1.

15ms:现在房间有3个用户,最多两个。

15ms: Now room has 3 users and the max was two.

如果异步性以每行为基础,那么如何避免上一个示例在实际情况下发生?抱歉,如果我没有用它们的名字来称呼事物,但我想不出一种更好的方式来解释这一点。

If asynchronicity goes on a 'per line' basis, how do I avoid the previous example to happen in a real scenario? Sorry if I haven't called things by their name, but I can't think of a better way to explain this.

评论暗示(但不要说) (肯定且清楚地)相同功能的实例永远不会重叠。

The comments suggest (but don't say for sure and in a clearly manner) that 'instances' of the same function won't ever overlap each other. What about different functions pointing to the same object/array?

join(user) {
    if(GLOBAL.room1.length === 2) throw new Error('The room is full');
    GLOBAL.room1.push(user);
};

join2(user) {
    if(GLOBAL.room1.length === 2) throw new Error('The room is full');
    GLOBAL.room1.push(user);
};


推荐答案

每个事件的Javascript都是同步的(作用域比功能或一行)。这不包括您自己启动的任何异步操作。他们将开始,然后在一段时间后以自己的事件结束(请参见此处稍后的事件讨论)。事件的同步代码(如您显示的内容)将完全运行到下一个事件可以运行之前。

Javascript is synchronous per event (a greater scope than a function or a line). This excludes any asynchronous operations you start yourself. They will start and then complete some time later with their own event (see discussion of events later on here). Synchronous code for an event (like what you show) will run entirely to completion before the next event can be run.

您在nodejs中的javascript以单线程和事件驱动的方式运行。这意味着一个Javascript开始执行,它将在其他事件可以处理之前完成。这样,一个函数可以运行并完成,然后任何人都可以再次调用它(假定它没有调用自身),因此您没有多线程环境中可能存在的典型竞争条件类型。

Your javascript in nodejs runs as single-threaded and event driven. That means that one a piece of Javascript starts executing, it will finish before any other events can be processed. As such, a function runs and completes before anyone can call it again (assuming it doesn't call itself) so you do not have the typical types of race conditions that can exist in a multi-threaded environment.


如果异步基于功能,则此代码100%防弹。一个房间中不可能有两个以上的用户。

If asynchronicity goes on a 'function' basis, this code is 100% bulletproof. There's no way there can be more than two users in a room.

node.js中的Javascript是单线程的,它将运行整个事件处理程序在下一个事件运行之前完成操作(该事件处理程序中的所有函数)。

Javascript in node.js is single-threaded and it will run an entire event handler to completion (all functions in that event handler) before running the next event.


如果异步性是基于每行的,则此代码可能会失败。为什么?因为如果三个用户同时进入房间,则可能在10毫秒的间隔内发生以下情况:

If asynchronicity goes on a 'per line' basis, this code may fail. Why? Because if three users enter the room at the same time, the following may happen in a 10ms interval:

JavaScript的单线程不是按行或按功能。每次活动。因此,在这种情况下,您似乎正在处理传入的socket.io消息。这意味着该传入消息事件处理程序中的所有代码将在可以处理任何其他传入消息之前运行。只有当事件处理程序将控制权返回给系统时(从其事件处理程序函数返回),nodejs才会在事件队列中获取下一个事件并调用其事件处理程序。

Javascript's single threadedness is not per line or per function. It's per event. So, in this case it appears you're probably handling an incoming socket.io message. That means that all code in that incoming message event handler will run before ANY other incoming messages can be processed. Only when your event handler returns control back to the system (by returning from its event handler function) will nodejs get the next event in the event queue and call its event handler.

所以,让我们说三个用户都要求大约在同一时间加入同一个房间,并检查该场景以进一步解释其工作原理。

So, let's say that three users are all asking to join the same room at about the same time and examine that scenario to explain further how this works.


  1. 所有三个客户都问大约在同一时间加入同一房间。

  2. 其中一个请求比另一个请求稍早到达(传入的数据包在网络电缆和传入的TCP堆栈中进行序列化,因此其中一个它们首先到达。)

  3. 该数据包由本地TCP堆栈处理,然后向nodejs中的侦听套接字发出警报(这将是本机代码,并在与JS不同的线程中运行)引擎)。

  4. nodejs平台代码获取此套接字通知,并将事件插入到nodejs事件队列中,以提醒nodejs代码监听该传入消息g消息。

  5. 如果nodejs Javascript引擎当前未执行任何操作,则它将立即触发该事件处理程序并开始运行与该事件处理程序关联的代码。

  6. 如果nodejs Javascipt引擎当前正在执行某项操作,则该事件将一直位于事件队列中,直到JS引擎完成其当前正在执行的操作,然后再获取事件队列中的下一个事件。

  7. 现在其他两个也加入同一个房间的请求到达TCP堆栈。

  8. nodejs中用于处理传入TCP数据包的本机代码,请参见这两个请求中的每一个都到达。就像第一个一样,它们被插入到nodejs事件队列中。因为JS解释器正忙于处理到达的第一条消息,所以这些消息现在仅位于事件队列中。

  9. 当第一条消息完成处理时,nodejs解释器将获取下一个事件。从事件队列中获取(第二个到达的消息将立即得到处理)。它的事件处理程序将被调用,并且将在处理第三个事件之前运行到完成。

  1. All three clients ask to join the same room at about the same time.
  2. One of those requests arrives marginally sooner than the other (incoming packets are serialized on the network cable and in the incoming TCP stack so one of them arrives first).
  3. That packet is processed by the local TCP stack and then the listening socket in nodejs is alerted (this would be in native code and runs in a different thread from the JS engine).
  4. The nodejs platform code gets this socket notification and inserts an event into the nodejs event queue to alert the nodejs code listening for that incoming message.
  5. If the nodejs Javascript engine is not doing anything at the moment, then it immediately fires that event handler and starts running the code associated with that event handler.
  6. If the nodejs Javascipt engine is doing something at the moment, then the event sits in the event queue until the JS engine finishes what it is currently doing and then it fetches the next event in the event queue.
  7. Now the other two requests to also join the same room arrive on the TCP stack.
  8. The native code in nodejs that is servicing incoming TCP packets, see each of these two requests arrive. They are inserted into the nodejs event queue just like the first one was. Because the JS interpreter is busy servicing the first message that arrived, these just sit in the event queue for now.
  9. When the first message finishes its processing, the nodejs interpreter, gets the next event from the event queue (whichever message arrived second will get processed now). Its event handler will be called and will run to completion before the third event is processed.

希望通过这种处理方式的描述,您可以看到您检查房间的长度没有任何可能的比赛条件。将用户添加到会议室是单线程的,因此它将在处理加入会议室的任何其他请求之前开始,进行和完成。这种单线程性质(有时是一个限制功能)极大地简化了nodejs编程,因为它消除了多线程编程所产生的许多竞争条件的可能原因。

Hopefully from this description of how things are processed, you can see that your check of the room length does not have any possible race conditions. The adding of a user to the room is single threaded so it will start, progress and complete before any other requests to join the room can be processed. This single-threaded nature (while occasionally a limiting feature) vastly, vastly simplifies nodejs programming because it removes many of the possible causes of race conditions that multi-threaded programming has.

让我们看看您的顺序,并在每一步中给出我的意见:

Let's look at your sequence with my comments on each step:


1ms:房间是空的。让用户A进入阵列。

1ms: Room is empty. Let User A in, push to array.

4ms:会议室有一个用户。

4ms: Room has one user.

5ms:用户B请求加入。

5ms: User B asks to join.

如果第一个请求尚未完成处理,该请求将被放入事件队列,直到第一个请求完成。如果第一个请求完成,则该请求将开始处理。

If the first request is not done processing yet, this request will be put in the event queue until that first request is done. If the first request is done, then this request will start processing.


6ms:用户C要求加入。

6ms: User C asks to join.

假设第二个请求需要花费超过1毫秒的时间来处理,因此尚未完成,该请求将进入事件队列,直到前两个请求都完全完成后才会被处理。 / p>

Assuming the second request takes more than 1ms to process so it's not done yet, this request will go in the event queue and will not be processed until both of the first two requests are completely done.


7ms:检查数组的长度(1)。

7ms: Check array for length (1).

我不了解此步骤的含义。如果这是处理第二个请求的一部分,则第二个和第三个请求仍在事件队列中,直到第一个请求完成后才能运行。

I don't understand what this step is meant to be. If this is part of processing the second request, then the second and third requests are still in the event queue and cannot run until the first one is done.


8ms:检查数组的长度(1)。

8ms: Check array for length (1).

与先前的注释相同。


9ms:因为房间长度为1,将用户B推送到数组。

9ms: Push user B to array because room length is 1.

10ms:因为房间长度为1,将用户C推送到数组。

10ms: Push user C to array because room length is 1.

15毫秒:现在房间有3个用户,最多两个。

15ms: Now room has 3 users and the max was two.

这是有缺陷的逻辑。由于事件队列和nodejs Javascript的单线程性质,因此只有在完成userA请求之后,userB和userC请求才会运行。因此,在运行任何请求时,房间长度始终是准确的。这样的多个请求不会同时运行。

This is flawed logic. Because of the event-queue and the single threaded nature of nodejs Javascript, the userB and userC requests do not run until the userA request is done. Thus, the room length is always accurate when any request runs. Multiple requests like this do not run at the same time.

这篇关于a)函数或b)代码行的异步性是常数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆