如何理解JavaScript是一种单线程非阻塞脚本语言?

从Javascript的设计上而言,是一门单线程非阻塞脚本语言,如何理解?

阅读 4.7k
4 个回答

我们都知道,javascript从诞生之日起就是一门单线程的非阻塞的脚本语言。这是由其最初的用途来决定的:与浏览器交互。

单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务。

而非阻塞则是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调。

单线程是必要的,也是javascript这门语言的基石,原因之一在其最初也是最主要的执行环境——浏览器中,我们需要进行各种各样的dom操作。试想一下 如果javascript是多线程的,那么当两个线程同时对dom进行一项操作,例如一个向其添加事件,而另一个删除了这个dom,此时该如何处理呢?因此,为了保证不会 发生类似于这个例子中的情景,javascript选择只用一个主线程来执行代码,这样就保证了程序执行的一致性。

当然,现如今人们也意识到,单线程在保证了执行顺序的同时也限制了javascript的效率,因此开发出了web worker技术。这项技术号称让javascript成为一门多线程语言。

然而,使用web worker技术开的多线程有着诸多限制,例如:所有新线程都受主线程的完全控制,不能独立执行。这意味着这些“线程” 实际上应属于主线程的子线程。另外,这些子线程并没有执行I/O操作的权限,只能为主线程分担一些诸如计算等任务。所以严格来讲这些线程并没有完整的功能,也因此这项技术并非改变了javascript语言的单线程本质。

可以预见,未来的javascript也会一直是一门单线程的语言。

跟银行排队一样,只有一个窗口,也即单线程,一个一个来服务,当某个人因为临时有事要耽搁一下,就出来,办完事之后再继续排,所以就是非阻塞了

这个问题可分成两部分来解释:

单线程

javascript 运行时只包含 一个消息队列,这里的每个消息都对应一个相关联的函数。这个队列遵循 FIFO(first in first out)机制,总是从最先进入的消息开始处理,处理时:

  1. 这个消息就会被移出队列,并拿着这个消息找到其对应的函数
  2. 函数开始执行,一直到执行完成
  3. 在消息队列中取下一个消息,再转到 1

非阻塞

在进行 IO 或者网络请求时,一般都是通过 事件回调机制 来进行的,例如当发送一个 json 异步数据请求后,就会认为这个函数执行完成了,会继续从消息队列中获取下一个消息来处理。等到网络请求返回后,会向队列中塞入一个新消息,继续等候处理。

但也是有例外的,比如 alert 对话框或者是同步XHR ,如果没有处理完成,消息队列会是一直阻塞的。当然,除非特殊场合,我们要尽量避免这种情况发生

你只要理解单线程就好了,非阻塞是说它的异步吧,其实还是借由宿主环境底层的多线程或者多进程去实现,怎么实现它不管,你能玩的就那么一个线程,设计上就是这么设计的,但是实现上又有各种玩法,所以强调设计上而言

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题