线程和进程的概念
进程:进程是正在运行的程序的实例。它包含了程序代码、数据、系统资源等,每当电脑开启一个程序,就相当于开启了一个进程。
线程:线程是进程的一部分,是一个执行路径。一个进程可以包含多个线程,它们共享进程的资源和上下文。
特点:
- 每个进程都有独立的内存空间,不同进程之间无法直接访问对方的内存。
- 进程之间是相互独立的,一个进程的崩溃不会影响其他进程。
- 线程之间共享同一进程的地址空间,可以直接访问进程的内存。
- 多个线程之间共享相同的资源,包括文件句柄、打开的网络连接等。
- 一个进程中的多个线程之间可以方便地进行通信,因为它们共享相同的上下文。
- 当一个进程关闭之后,操作系统会回收该进程的内存空间
多进程的浏览器
浏览器从关闭到启动,然后新开一个页面至少需要:1个浏览器进程,1个GPU进程,1个定时器引擎,1个网络进程,和1个渲染进程,1个插件进程;
浏览器的主进程(只有一个),负责协调、主控。
各个进程的作用
渲染进程
- 渲染浏览器界面,解析HTML,CSS,创建DOM,布局绘制都需要该进程
- 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行
这里面包括
- GUI渲染线程
- JavaScript引擎线程
- 事件触发线程
- 定时器线程
- 异步http请求线程
GPU进程
用于3D绘制,将开启了3D绘制的元素渲染由CPU转向GPU,最多一个。
定时器进程
- 如其名,就是处理setTimeout,setInterval的线程
- 浏览器定时计数器并不是由 JavaScript 引擎计数的,(因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)。
网络进程
- 在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求。
- 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由 JavaScript 引擎执行。
插件进程
每种类型的插件对应一个进程,仅当使用该插件时才创建,当一个插件出现了错误,并不会影响主线程。
浏览器里面的线程
JS引擎线程
- 负责处理JS的脚本的进程
- 渲染线程与 JS 引擎线程是互斥的,所以如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。
事件触发线程
- 用来控制事件循环的,该任务不是属于JS引擎进程的而属于事件触发进程,也就是JS引擎忙不过来,再开了一个进程来处理
- 当遇到一些异步请求耗时的任务,会把他们放到任务队列里面
定时器线程
- 如其名,就是处理setTimeout,setInterval的线程
- 浏览器定时计数器并不是由 JavaScript 引擎计数的,(因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确)。
网络请求线程
- 在 XMLHttpRequest 在连接后是通过浏览器新开一个线程请求。
- 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中。再由 JavaScript 引擎执行。
主线程和内核进程之间的通信
- Browser 进程收到用户请求,首先需要获取页面内容(譬如通过网络下载资源),随后将该任务通过 RendererHost 接口传递给 Render 进程。
- Renderer 进程的 Renderer 接口收到消息,简单解释后,交给 GUI 渲染线程,然后开始渲染。
- 渲染线程接收请求,加载网页并渲染网页,这其中可能需要 Browser 进程获取资源和需要 GPU 进程来帮助渲染。
- 当然可能会有 JS 线程操作 DOM(这样可能会造成回流并重绘)。
- 最后 Render 进程将结果传递给 Browser 进程。
- Browser 进程接收到结果并将结果绘制出来
进程之间的通信方式(了解即可)
-
管道通信:就是操作系统在内核中开辟一段缓冲区,进程1可以将需要交互的数据拷贝到这个缓冲区里,进程2就可以读取了 -
消息队列通信:消息队列就是用户可以添加和读取消息的列表,消息队列里提供了一种从一个进程向另一个进程发送数据块的方法,不过和管道通信一样每个数据块有最大长度限制 -
共享内存通信:就是映射一段能被其他进程访问的内存,由一个进程创建,但多个进程都可以访问,共享进程最快的是IPC方式 -
信号量通信:比如信号量初始值是1,进程1来访问一块内存的时候,就把信号量设为0,然后进程2也来访问的时候看到信号量为0,就知道有其他进程在访问了,就不访问了 -
socket:其他的都是同一台主机之间的进程通信,而在不同主机的进程通信就要用到socket的通信方式了,比如发起http请求,服务器返回数据
多标签之间的通信
- localstorage: 同域共享存储空间,持久化将数据存储来浏览器,提供事件监听localStorage变化
- websocket:它是一个全双工通信的协议,意味着客户端和服务端可以互相通信,享受平等关系。最简单例子就是聊天室,我们在聊天室里面可以收消息,也可以发消息,只要我们与服务端通过websocket建立好了连接。没有同源共享策略,即可实现跨域共享
- SharedWorker:sharedWorker就是webWorker中的一种,它可以由所有同源页面共享,利用这个特性,我们就可以使用它来进行多标签页之间的通信。如果url相同,且是同一个js,那么只会创建一个sharedWorker,多个页面共享这个sharedWorker
- webWorker:Web Worker 为代码在后台线程中运行脚本提供了一种简单方法,线程可以执行任务而不干扰用户界面。
// 发送方
window.parent().postMessage('发送的数据','http://接收的址')
// 接收方
window.addEventListener('message',(e)=>{ let data = e.data })
总结
- 浏览器是多进程的
- JS引擎是单线程的,并且会阻塞GUI渲染线程