并发模型与Event Loop

JavaScript的并发模型基于"event loop"。这个模型与其他在C或者Java中的模型着实不同。

运行时概念

下面的内容解释了一个理论上的模型。现代JavaScript引擎着重实现和优化了描述的几个语义。

可视化描述

函数调用形成了一个frames的栈。

function f(b){
  var a = 12;
  return a+b+35;}function g(x){
  var m = 4;
  return f(m*x);}g(21);

调用g的时候,创建了第一个frame,包含了g的变量以及其本地变量。当 g 调用 f 的时候,第二个frame就被创建、并置于第一个frame之上,包含了f的参数和本地变量。当f返回时,最上层的frame就出栈了(剩下g函数调用的frame)。当g返回的时候,栈就空了。

对象被分配在一个堆中,一个用以表示一个内存中大的未被组织的区域。

队列

一个JavaScript运行时包含了一个待处理的消息队列。每一个消息都与一个函数相关联。当栈为空时,从队列中取出一个消息进行处理。这个处理过程包含了调用与这个消息相关联的函数(以及因此而创建的一个初始栈结构)。当栈再次为空的时候,也就意味着消息处理结束。

事件循环

之所以称为 事件循环,是因为它经常被用于类似如下的方式来实现:

while(queue.waitForMessage()){
  queue.processNextMessage();
}

如果当前没有任何消息,queue.waitForMessage 会同步等待消息到来。

"执行至完成"

每一个消息执行完成后,其它消息才会被执行。当你分析你的程序时,这点提供了一些优秀的特性,包括当一个函数运行时,它不能被取代且会在其它代码运行前先完成(而且能够修改这个函数控制的数据)。这点与C语言不同。例如,C语言中当一个程序在一个线程中运行时,它可以在任何点停止且可以在其它线程中运行其它代码。

这个模型的一个缺点在于当一个消息的完成耗时过长,网络应用无法处理用户的交互如点击或者滚动。浏览器用“程序需要过长时间运行”的对话框来缓解这个问题。一个比较好的解决方案是使消息处理变短且如果可能的话,将一个消息拆分成几个消息。

添加消息

在浏览器里,当一个事件出现且有一个事件监听器被绑定时,消息会被随时添加。如果没有事件监听器,事件会丢失。所以点击一个附带点击事件处理函数的元素会添加一个消息。其它事件亦然。

调用 setTimeout 函数会在一个时间段过去后在队列中添加一个消息。这个时间段作为函数的第二个参数被传入。如果队列中没有其它消息,消息会被马上处理。但是,如果有其它消息,setTimeout消息必须等待其它消息处理完。因此第二个参数仅仅表示最少的时间 而非保证的时间。

几个运行时(Runtime)互相通信

一个web worker或者一个跨域的iframe都有它们自己的栈,堆和消息队列。两个不同的运行时只有通过postMessage方法进行通信。这个方法会给另一个运行时添加一个消息如果后者监听了message事件。

绝不阻塞

一个很有趣的事件循环(event loop)模型特性在于,Javascript跟其它语言不同,它永不阻塞。处理I/O (input/output)通常由事件或者回调函数进行实现。所以当一个应用正等待IndexedDB的查询的返回或者一个XHR(译者注:用于Ajax)的请求返回时,它仍然可以处理其它事情例如用户输入。

例外是存在的,如alert或者同步XHR,但避免它们被认为是最佳实践。注意的是,例外的例外也是存在的(但通常是实现错误而非其它原因)。

时间: 2024-09-29 12:46:44

并发模型与Event Loop的相关文章

数据密集型 和 cpu密集型 event loop

Node.js在官网上是这样定义的:“一个搭建在Chrome JavaScript运行时上的平台,用于构建高速.可伸缩的网络程序.Node.js采用的事件驱动.非阻塞I/O模型使它既轻量又高效,是构建运行在分布式设备上的数据密集型实时程序的完美选择.”Web站点早已不仅限于内容的呈现,很多交互性和协作型环境也逐渐被搬到了网站上,而且这种需求还在不断地增长.这就是所谓的数据密集型实时(data-intensive real-time)应用程序,比如在线协作的白板,多人在线游戏等,这种web应用程序

为什么要了解Event loop?(二)

转载于http://www.jianshu.com/p/1ee6c21f6efa 为什么要了解Event loop? 理解Event loop,对于浏览器(或者nodejs)处理事件的过程会有更透彻的理解,使用promise,nextTick, setImmediate,setTimeout等会更清晰.本文主要是基于浏览器端来理解的. <small>有部分术语还是采用英文,看上去感觉比中文好理解</small> 参考自: Tasks, microtasks, queues and

Javascript Event Loop

Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制. JavaScript语言就采用这种机制,来解决单线程运行带来的一些问题. 本文参考C. Aaron Cois的<Understanding The Node.js Event Loop>,解释什么是Event Loop,以及它与JavaScript语言的单线程模型有何关系. 想要理解Event Loop,就要从程序的运行模式讲起.运行以后的程序叫做"进程"(process),一般情况下,一个进程一次

以setTimeout来聊聊Event Loop

平时的工作中,也许你会经常用到setTimeout这个方法,可是你真的了解setTimeout吗?本文想通过总结setTimeout的用法,顺便来探索javascript里面的事件执行机制. setTimeout基本用法 1. setTimeout(code,millisec) setTimeout函数接受两个参数,第一个参数code是将要推迟执行的函数名或者一段代码,第二个参数millisec是推迟执行的毫秒数. 例如: setTimeout(‘console.log(2)’,100); se

linux --&gt; Event Loop介绍

Event Loop介绍 想要理解Event Loop,就要从程序的运行模式讲起.运行以后的程序叫做"进程"(process),一般情况下,一个进程一次只能执行一个任务. 如果有很多任务需要执行,不外乎三种解决方法. (1)排队.因为一个进程一次只能执行一个任务,只好等前面的任务执行完了,再执行后面的任务. (2)新建进程.使用fork命令,为每个任务新建一个进程. (3)新建线程.因为进程太耗费资源,所以如今的程序往往允许一个进程包含多个线程,由线程去完成任务. 以JavaScrip

web并发模型

并发:cpu划分时间片,轮流执行每个请求任务,时间片到期后,换到下一个. 并行:在多核服务器上,每个cpu内核执行一个任务,是真正的并行 IO密集型的应用,由于请求过程中很多时间都是外部IO操作,CPU在wait状态,所以并发执行可以有效提高系统吞吐量 纯CPU密集型的应用:在单核上并发执行多个请求,不能提高系统吞吐量(由于任务来回场景切换的开销,吞吐量反而会下降);只有多核并行运算,才能有效提高吞吐量 web并发模型有:multi-process   multi-thread    multi

Event Loop、函数式编程、IO多路复用、事件驱动、响应式、

IO多路复用.事件驱动.响应式概念类似或者一样 就是很多网络连接(多路),共(复)用少数几个(甚至是一个)线程. 连接很多的时候,不能每个连接一个线程,会耗尽系统内存的.线程也不能阻塞在任何一个连接上,等新的数据来,这样就不能及时响应其他连接发来的数据了:也不能用非阻塞方式,轮询所有的连接,这会浪费掉大量CPU时间:只能告诉系统,我对哪些连接感兴趣,有消息来的时候,通知我处理. IO多路复用: 一种在后端网络编程中的一种技术 IO多路复用机制详解    服务器,并发,"事件驱动"的本质

深入理解JavaScript的事件循环(Event Loop)

一.什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为 因为它经常被用于类似如下的方式来实现 while (queue.waitForMessage()) { queue.processNextMessage(); } 如果当前没有任何消息queue.waitForMessage 会等待同步消息到达 我们可以把它当成一种程序结构的模型,处理的方案.更详细的描述可以查看 这篇文章 而JS的运行环境主要有两个:浏览器.Node. 在两个环境下的Event

nginx并发模型与traffic_server并发模型简单比较

ginx并发模型: nginx 的进程模型采用的是prefork方式,预先分配的worker子进程数量由配置文件指定,默认为1,不超过1024.master主进程创建监听套接口,fork子进程以后,由worker进程监听客户连接,每个worker子进程独自尝试accept已连接套接口,accept是否上锁可以配置,默认会上锁,如果操作系统支持原子整型,才会使用共享内存实现原子上锁,否则使用文件上锁.不使用锁的时候,当多个进程同时accept,当一个连接来的时候多个进程同时被唤起,会导致惊群问题.