什么是进程和线程
进程
进程是操作系统进行资源分配
和独立运行
的最小单元。进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成
当我们启动一个应用
,计算机会至少创建一个进程,cpu会为进程分配一部分内存
,应用的所有状态都会保存在这块内存中,应用也许还会创建多个线程来辅助工作,这些线程
可以共享这部分内存中的数据
。如果应用关闭,进程会被终结,操作系统会释放相关内存。
多核CPU:多进程
单核CPU:单进程
复制代码
Windows可以在任务管理器中查看启动的进程数:
进程之间的通信方式
- 管道
- 消息队列:由消息组成的链表
- 信号量:一个计数器,可以用来控制多个进程对共享资源的访问
进程之间不共享的有:
- 资源
- 内存空间
线程
进程内部的一个执行单元,是被系统独立调度
和分派
的基本单位。系统创建好进程后,实际上就启动执行了该进程的主线程
进程就像是一个有边界的生产厂间,而线程就像是厂间内的一个个员工,可以自己做自己的事情,也可以相互配合做同一件事情,所以一个进程可以创建多个线程
。
线程自己不需要系统重新分配资源,它与同属一个进程的其它线程共享当前进程所拥有的全部资源。
PS:
进程之间是不共享资源和地址空间的,所以不会存在太多的安全问题,而由于多个线程共享着相同的地址空间和资源,所以会存在线程之间有可能会恶意修改或者获取非授权数据等复杂的安全问题。
线程之间共享的有:
- 资源
- 文件
- 变量
- 内存空间
如何解决因为共享引发的冲突?
互斥锁
:防止多个线程同时读写某一块内存区域
打个比方:一车间一人,先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去
信号量
:用来保证多个线程不会互相冲突
打个比方:一车间多人,门口放一串钥匙串,进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了
线程之间不共享的资源
- 栈
- 寄存器
操作系统的设计,可以归结为三点:
- 以多进程形式,允许多个任务
同时
运行; - 以多线程形式,允许单个任务分成
不同
的部分运行; - 提供协调机制:
- 一方面防止进程之间和线程之间
产生冲突
- 另一方面允许进程之间和线程之间
共享资源
- 一方面防止进程之间和线程之间
浏览器的多进程
以 Chrome 为例
每打开一个tab页,就相当于于创建了一个独立的浏览器进程
浏览器的主要进程及其职责
- 浏览器进程:浏览器的主进程(
负责协调、主控
)
- 负责包括地址栏,书签栏,前进后退按钮等部分的工作
- 负责处理浏览器的一些不可见的底层操作,比如网络请求和文件访问
- 负责各个页面的管理,创建和销毁其他进程
- 渲染进程:负责一个 tab 内关于
网页呈现
的所有事情,页面渲染
,脚本执行
,事件处理等
- 插件进程:负责
管理所有插件
,如 flash,每种类型的插件对应一个进程,仅当使用该插件时才创建 - GPU进程:负责处理 GPU 相关的任务
浏览器多进程的优缺点
- 优点:
(1)某一渲染进程出问题不会影响其他进程
(2)更为安全,在系统层面上限定了不同进程的权限
- 缺点:
由于不同进程间的内存不共享,不同进程的内存常常需要包含相同的内容
。为了节省内存,Chrome 限制了最多的进程数,最大进程数量由设备的内存和 CPU 能力决定,当达到这一限制时,新打开的 Tab 会共用之前同一个站点的渲染进程。
Chrome 把浏览器不同程序的功能看做服务,这些服务可以方便的分割为不同的进程或者合并为一个进程。
浏览器的多线程
对于前端而言,最多关注的是渲染进程:
- 每个tab页对应一个渲染进程
- 每个渲染进程负责HTML、,css,js等文件的解析,执行和渲染,以及事件处理等
- 每个渲染进程由多个线程构成:(1)GUI线程;(2)JS引擎线程;(3)事件触发线程;(4)定时器线程;(5)异步的http网络请求线程
1. GUI渲染线程
负责页面渲染,GUI渲染引擎是浏览器内核的核心部分
具体渲染过程见 浏览器系列 — 渲染原理及过程
2. JavaScript 引擎线程
负责解析Javascript脚本,运行代码
3. 定时触发器线程
浏览器定时计数器并不是由 JavaScript 引擎计数的, 因为 JavaScript 引擎是单线程的, 如果处于阻塞线程状态就会影响记计时的准确, 因此通过单独线程来计时并触发定时
具体内容见 JavaScript系列 — 定时器
4. 事件触发线程
当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待 JavaScript 引擎的处理
具体内容见 JavaScript系列 — Eventloop机制
5. 异步http请求线程
XMLHttpRequest 请求会在浏览器中新开一个线程请求, 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件放到 JavaScript 引擎的处理队列中
具体内容见 JavaScript系列 — 异步编程
另外注意:不同浏览器的内核实现有所差异,导致对网页编写语法的解释也有不同(JS引擎线程),因此同一网页在不同的内核的浏览器里的渲染结果也可能不同(GUI渲染线程),这就抛出了常见的 “浏览器兼容性问题”