赞
踩
进程:
进程是系统中正在运行的一个程序,程序一旦运行就是进程。进程可以看成程序执行的一个实例,可以视作为浏览器打开了多个tab页,每个tab页相当于独立的进程。进程是系统资源分配的独立实体,每个进程都拥有独立的地址空间。一个进程无法访问另一个进程的变量和数据结构,如果想让一个进程访问另一个进程的资源,需要使用进程间通信,比如管道,文件,套接字等。
一个进程可以拥有多个线程,每个线程使用其所属进程的栈空间。线程与进程的一个主要区别是,统一进程内的一个主要区别是,同一进程内的多个线程会共享部分状态,多个线程可以读写同一块内存(一个进程无法直接访问另一进程的内存)。同时,每个线程还拥有自己的寄存器和栈,其他线程可以读写这些栈内存。
线程:
线程是进程的一个实体,是进程的一条执行路径。
线程是进程的一个特定执行路径。当一个线程修改了进程的资源,它的兄弟线程可以立即看到这种变化。
线程和进程的区别:
1.地址空间和其他资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其他进程内不可见。
2.通信:进程间通信IPC(管道,信号量,共享内存,消息队列),线程间可以直接独写进程数据段(如全局变量)来进程通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
3.调度和切换:线程上下文切换比进程上下文切换快得多。
4.在多线程OS中,进程不是一个可执行的实体。(看不懂,忽略不计)
2. 浏览器中的进程
1.浏览器进程(Browser进程)
浏览器的主进程,负责协调、主控,只有一个(无论打开几个tab或几个弹窗),主要作用:
2.CPU进程
用于3D绘制等,可禁用掉,只有一个。
3.第三方插件进程
每种类型的插件对应一个进程,仅当使用该插件时才创建。
4.浏览器渲染进程(浏览器内核)
浏览器渲染进程(render进程),即通常说的浏览器内核,主要作用是:页面渲染、脚本执行、事件处理等。每一个标签页的打开都会创建一个Render进程,并且互不影响。默认的话一个标签页对应一个Render进程,但是,有时候浏览器会将多个进程合并,如打开了多个空白标签页。
知识点:浏览器为什么是多进程的?
如果多个页面共用一个进程,在某个tab页崩溃时,将导致同进程中的其他页面崩溃,极其印象用户体验;而且进程之间是不会共享资源和地址空间的,所以不会存在太多的安全问题。当然,多进程相对于单进程而言,对内存等资源的消耗更大。
3.浏览器渲染进程中的线程
浏览器渲染进程(render进程,也成为浏览器内核),是我们前端开发人员最需要关注的。它主要的作用:页面渲染、脚本执行、事件处理等。它包含一下5种线程:
1.GUI渲染线程(有且只有一个)
小知识点:为什么JS引擎执行的时候GUI线程要被挂起?
因为JS是可以操作DOM的,而如果在修改这些元素的同时渲染界面,即当这两个线程不是互斥的时候,那么GUI渲染线程前后获得的元素数据就可能不一致。所以JavaScript引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎线程空闲时立即被执行。
2.JS引擎线程(有且只有一个)
3.事件触发线程
4.定时器触发线程(多个)
5.异步http请求线程(多个)
1.GUI渲染引擎和JS执行引擎互斥,当GUI渲染引擎解析html时,发现了script标签时,会立即挂起解析html的任务,然后开始解析js代码,直到所有js代码执行完成后,继续执行html解析渲染。
2.JS是单线程的,所以在处理某些任务如请求服务端数据,定时任务等,自顾不暇,需要其他兄弟线程的协助。
3.JS是基于事件驱动的,其需要一种事件循环机制和事件队列的夹持,即需要事件触发线程的配合,和其他线程之间亲密合作。
为什么JS是单线程的:
JS执行引擎是单线程的,就是说,每一个浏览器内核(Render进程中),有且只有一个JS执行引擎(web worker另谈),为什么只能有一个?这和JS的用途有关,JS作为浏览器的脚本语言,主要用处是与用户进行交互,以及操作DOM的,如果JS是多线程,当在不同线程进行不同的DOM操作,会造成更复杂的一些问题,所以从一开始,JS就是单线程的。
什么是同步任务:
JS单线程就意味着,我的代码必须是从上到下,一行一行执行。一个代码块执行完毕之后,才能进行另一个代码块的执行,这就是同步执行代码。(定义:同步执行:代码从上到下,一行一行执行,下方代码块的执行必须是等待其前面代码全部执行完成之后才能执行,若代码执行中报错,则其下方代码不再执行)
存在什么问题:
那么此时,我们想要从服务端获取某一些数据然后渲染到页面上,如果仍然是同步执行,我们需要等待数据全部加载完成之后,才能执行接下来的代码;如果这个数据的请求特别慢,那么页面就极其不友好。
如何解决:(异步回调)
异步回调是两个词,异步指的是,JS执行引擎会将某些任务挂起,交由他的兄弟线程进行处理,等到兄弟线程处理完成之后,JS执行引擎再回去执行其回调函数,他不会阻塞代码的执行,异步代码执行错误,不会影响其他同步代码的执行。而回调函数指的是,我先定了一个函数,但是目前我不想调用,当在某个事情发生或者到了某个特定的时间,我会去调用这个函数,这个就称为回调函数。
异步执行基于回调函数。异步执行基于回调函数。异步执行基于回调函数。
什么任务会触发异步:
回调函数的应用场景:
JS执行引擎,会召唤其兄弟线程来帮助他来进行一些操作,在这些操作执行完成之后,将对这些操作结果进行处理。如下图所示:
第一次理解:
Browser进程请求服务端,服务端返回了html资源
线程切换的顺序:
- => 事件触发线程
- GUI渲染线程 => JS执行线程 => 异步http线程 => 推到事件队列(事件触发线程) => GUI渲染线程(如果仍有等待的任务) => JS执行线程
- => 定时器线程
事情走到这一步基本上是破案了,但是仍有一个前端面试经常碰到的问题,什么是宏任务,什么是微任务。
宏任务与微任务
概念一:宿主
JS运行的环境。一般为浏览器或者Node。
概念二:宏任务和微任务
在ES3以及以前的版本中,JavaScript本身没有发起异步请求的能力,也就没有微任务的存在。在ES5之后,JavaScript引入了Promise,这样,不需要浏览器,JavaScript引擎自身也能够发起异步任务了。
- ES6 规范中,microtask 称为 jobs,macrotask 称为 task
- 即 微任务是ES对异步的定义;而宏任务是浏览器对异步的定义。
- jobs 包括 Promise, async/await
- task 包括 script,定时任务,ajax请求,事件回调
- 宏任务是由宿主发起的,而微任务由JavaScript自身发起。
第二次理解:
至此,完结。
不知道大家还记不记得小学生活有一道算术题:
如果洗衣机洗衣服需要花30分钟,电饭锅煮饭需要40分钟,打扫卫生需要20分钟,听歌需要15分钟。
那么请问家里有多少人?- -。
问完成这些工作,最快需要多少时间,以及最慢需要多少时间。
如果规定,这些工作必须是一项接着一项完成,某一项未完成的时候不能进行下一项的工作,那么这个就相当于计算机中的同步。那么我还需要坐着看洗衣机洗衣服,看电饭煲煮饭,最终需要的时间是 30+40+20+15=105分钟,我太遭罪了。
如果不规定必须是一件一件完成,一件事情发生的同时,不管这件事情完成与否,另外的一件或者多件事情都仍能够发生。所以上面的问题,我只需要再买个扫地机器人,就只需要花15分钟的时间就能够完成了。
言归正传,JS在发明的起初,主要的目的是为了实现用户与浏览器的交互。那为什么是单线程的?单线程是相对比与多线程而言的,单线程的意思是值在JS引擎中负责解释和执行JavaScript代码的线程只有一个。试想一下,如果JS同时拥有两个线程,A线程在某个DOM上新增了内容,而B节点又删除了这个节点,此时的浏览器可能就傻了,所以为了避免复杂性,从一诞生,就只有一个负责解释和执行JS代码的线程。
正是因为是单线程,所以就导致了上述的规定,事情必须是一件一件发生的,代码必须是一行一行执行的。那就有问题了,比如说电饭煲煮饭需要40分钟,那我就眼睁睁看着生米怎么煮成熟饭么?
那我岂不是脑子有泡了。生活中存在这样的问题,那浏览器中是否也有这样的问题。比如说,有一个AJAX请求,从数据库获取数据,需要1分钟的时间,那我触发了该事件之后,如果说所所有任务都是同步的,那么在我请求的过程中,这一分钟内,我就相当一直盯着电饭煲看生米煮成熟饭。我们脑子没有泡,浏览器肯定也不傻。
所以就存在一个,你执行事件时间太长,而我没耐心等你的场景。如果一直等你,其他的代码就一直执行不了,就称之为阻塞,也就是卡死,正常人的操作就是刷新试试,而刷新完你还是继续执行了很长时间,人们就会破口代码,这*****。
如何解决异步,就需要使用回调函数来解决,实现方式如上所示。
本文参考:感恩各位大佬
浏览器的线程和进程www.jianshu.com
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。