首页 web前端 前端问答 JavaScript的单线程你真的理解了吗

JavaScript的单线程你真的理解了吗

Jan 10, 2022 pm 07:08 PM
html javascript 前端

本篇文章给大家带来了我们的JavaScript单线程的相关知识,JavaScript是一门单线程的语言,为什么JavaScript可以一边执行定时器一边执行函数,希望对大家有帮助。

JavaScript的单线程你真的理解了吗

1. 进程与线程

1.1 进程(Process)

是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。 在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。程序是指令、数据及其组织形式的描述,进程是程序的实体。

我们这里将进程比喻为工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。

1.2 线程(thread)

是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

这里把线程比喻一个车间的工人,即一个车间可以允许由多个工人协同完成一个任务。

2. 多线程的浏览器

浏览器内核是多线程,在内核控制下各线程相互配合以保持同步,一个浏览器通常由以下常驻线程组成:

  • GUI 渲染线程

  • JavaScript引擎线程

  • 事件触发线程

  • 定时触发器线程

  • 异步http请求线程

43.png

我们看到了JS引擎线程,非常的熟悉,没有错,这里是我们执行javascript脚本程序的地方。

而JS引擎是多线程的,单线程是指JS引擎执行JS时只分了一个线程给他执行,意思是JS引擎分配了一个线程给JavaScript执行,也就是我们所说的单线程。

2.1 这里再说下JS的执行机制

由于JavaScript是单线程(一个Tab页内中无论什么时候都只有一个JS线程在运行JavaScript程序)。

所以我们需要依靠任务队列来进行JavaScript代码的执行。

JS引擎会一直等待着任务队列中任务的到来,然后执行任务。

同步任务这么执行当然没问题,我们把任务都放在任务队列里,一个一个执行,逻辑很清晰。但是,如果我们向后台发送请求,发送加接收这段时间可能需要一秒,我们不能等它一秒吧,如果请求五次,那就等五秒?显示不符合我们的需求,所以,我们需要异步任务来处理这个问题。

2.2 同步任务和异步任务

同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务,当我们打开网站时,网站的渲染过程,比如元素的渲染,其实就是一个同步任务

异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程,当我们打开网站时,像图片的加载,音乐的加载,其实就是一个异步任务。

大家肯定对Event Loop有比较具象的认知,这边我不详细说了,不懂可以和我说,我再讲就是了。

3. 本文重重点--可直接看

但是,大家有没有对任务队列抱有疑问?这是个对象?是个数组?按我的逻辑来说,我们JavaScript主线程执行同步函数,异步函数可以放在任务队列里,这个任务队列可以是个对象,当我们执行完同步任务的时候,把这个对象(任务队列)压进主线程中就可以了,但是事实并不我想的这样的。

Evnet Loop的任务队列放在了浏览器的事件触发线程中,当JS引擎执行异步函数的时候,会将异步任务放在事件触发线程中,当对应的异步任务符合触发条件被触发时,事件触发线程会把异步任务添加到JS引擎中的主线程的队尾,等待执行。

是不是和我们想象的JavaScript单线程不太一样?好吧,确实不太一样,所以最后的结论是,我们所说的任务队列竟然是一个线程。

然后,说回我们开头刚开始说过的定时器,大家基本也能猜出来了,它是由定时器线程控制的。

因为JavaScript是单线程的, 如果处于阻塞线程状态就会影响记计时的准确,因此很有必要单独开一个线程用来计时。

当使用setTimeout或setInterval时,它需要定时器线程计时,计时完成后就会将特定的事件推入事件队列中。

4. 结论

所以说,我们说JavaScript是单线程的没错,就是天王老子来了它也是单线程的,但是我们的Event Loop和定时器是放在其他线程中的。

5. V8引擎--扩展

V8引擎是一个JavaScript引擎实现,最初由一些语言方面专家设计,后被谷歌收购,随后谷歌对其进行了开源。

V8使用C++开发,在运行JavaScript之前,相比其它的JavaScript的引擎转换成字节码或解释执行,V8将其编译成原生机器码(IA-32, x86-64, ARM, or MIPS CPUs),并且使用了如内联缓存(inline caching)等方法来提高性能。

有了这些功能,JavaScript程序在V8引擎下的运行速度媲美二进制程序。V8支持众多操作系统,如windows、linux、android等,也支持其他硬件架构,如IA32,X64,ARM等,具有很好的可移植和跨平台特性。

5.1 工作流程

V8引擎在执行JavaScript的过程中,主要有两个阶段:编译和运行,与C++的执行前完全编译不同的是,JavaScript需要在用户使用时完成编译和执行。在V8中,JavaScript相关代码并非一下完成编译的,而是在某些代码需要执行时,才会进行编译,这就提高了响应时间,减少了时间开销。在V8引擎中,源代码先被解析器转变为抽象语法树(AST),然后使用JIT编译器的全代码生成器从AST直接生成本地可执行代码。这个过程不同于JAVA先生成字节码或中间表示,减少了AST到字节码的转换时间,提高了代码的执行速度。但由于缺少了转换为字节码这一中间过程,也就减少了优化代码的机会。

V8引擎编译本地代码时使用的主要类如下所示:

  • Script:表示JavaScript代码,即包含源代码,又包含编译之后生成的本地代码,即是编译入口,又是运行入口;

  • Compiler:编译器类,辅组Script类来编译生成代码,调用解释器(Parser)来生成AST和全代码生成器,将AST转变为本地代码;

  • AstNode:抽象语法树节点类,是其他所有节点的基类,包含非常多的子类,后面会针对不同的子类生成不同的本地代码;

  • AstVisitor:抽象语法树的访问者类,主要用来遍历异构的抽象语法树;

  • FullCodeGenerator:AstVisitor类的子类,通过遍历AST来为JavaScript生成本地可执行代码。

44.png

JavaScript代码编译的过程大致为:Script类调用Compiler类的Compile函数为其生成本地代码。Compile函数先使用Parser类生成AST,再使用FullCodeGenerator类来生成本地代码。本地代码与具体的硬件平台密切相关,FullCodeGenerator使用多个后端来生成与平台相匹配的本地汇编代码。由于FullCodeGenerator通过遍历AST来为每个节点生成相应的汇编代码,缺失了全局视图,节点之间的优化也就无从谈起

【相关推荐:javascript学习教程

以上是JavaScript的单线程你真的理解了吗的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

HTML 中的表格边框 HTML 中的表格边框 Sep 04, 2024 pm 04:49 PM

HTML 表格边框指南。在这里,我们以 HTML 中的表格边框为例,讨论定义表格边框的多种方法。

HTML 中的嵌套表 HTML 中的嵌套表 Sep 04, 2024 pm 04:49 PM

这是 HTML 中嵌套表的指南。这里我们讨论如何在表中创建表以及相应的示例。

HTML 左边距 HTML 左边距 Sep 04, 2024 pm 04:48 PM

HTML 左边距指南。在这里,我们讨论 HTML margin-left 的简要概述及其示例及其代码实现。

HTML 表格布局 HTML 表格布局 Sep 04, 2024 pm 04:54 PM

HTML 表格布局指南。在这里,我们详细讨论 HTML 表格布局的值以及示例和输出。

HTML 输入占位符 HTML 输入占位符 Sep 04, 2024 pm 04:54 PM

HTML 输入占位符指南。在这里,我们讨论 HTML 输入占位符的示例以及代码和输出。

HTML 有序列表 HTML 有序列表 Sep 04, 2024 pm 04:43 PM

HTML 有序列表指南。在这里我们还分别讨论了 HTML 有序列表和类型的介绍以及它们的示例

在 HTML 中移动文本 在 HTML 中移动文本 Sep 04, 2024 pm 04:45 PM

HTML 中的文本移动指南。在这里我们讨论一下marquee标签如何使用语法和实现示例。

HTML onclick 按钮 HTML onclick 按钮 Sep 04, 2024 pm 04:49 PM

HTML onclick 按钮指南。这里我们分别讨论它们的介绍、工作原理、示例以及各个事件中的onclick事件。

See all articles