乐趣区

Javascript探究javascript中的堆栈任务队列与并发模型-event-loop的关系

堆 / 栈 / 队列

在 javascript 中,存在 调用栈 (call stack) 内存堆 (memory heap) , 程序中函数依次进入栈中等待执行, 若执行时遇到异步方法, 该异步方法会被添加到用于回调的 任务队列(task queue)中,【即 JavaScript 执行引擎的单线程拥有一个调用栈、内存堆和一个任务队列】

调用栈 (call stack):CallStack 是用来处理函数调用与返回的。特点是先进后出, 每次调用一个函数,Javascript 运行时会生成一个新的调用结构压入 CallStack。而函数调用结束返回时,JavaScript 运行时会将栈顶的调用结构弹出。由于栈的 LIFO 特性,每次弹出的必然是最新调用的那个函数的结构。函数调用会形成了一个堆栈帧, 存放基本数据类型的变量

内存堆 (memory head): 引用数据类型被存放在堆中, 在我们进行浅复制时,我们改变的只是引用数据类型在栈内存中的引用地址,实际上它在堆内存中的引用地址仍然没有发生变化

任务队列(task queue):javaScript 运行时包含了一个待处理的任务队列。

并发模型 与 EventLoop

javascript 引擎是单线程的,它的并发模型基于Event Loop(事件循环)

当线程中的同步任务执行完,执行栈 为空时,则从 任务队列 (task queue) 中取出异步任务进行处理。这个处理过程包含了调用与这个任务相关联的函数(以及因而创建了一个初始堆栈帧)。当 执行栈 再次为空的时候,也就意味着该任务处理结束, 从任务队列中取出下一个异步任务进行处理,不断重复,这个过程是循环不断的, 所以整个的这种运行机制又称为Event Loop(事件循环).

Task Queue 任务队列

任务队列有 宏任务队列 微任务队列, 每次事件循环的时候,会先执行宏任务队列中的任务,然后再执行微任务队列中的任务。在当前的微任务没有执行完成时,是不会执行下一个宏任务的。

  • 宏任务:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering.
  • 微任务:process.nextTick, Promise, Object.observer, MutationObserver.
如果我的文章对你有帮助,欢迎关注我的博客,JS/Python/ 算法系列, 码不停题!!!
退出移动版