进程和线程:进程的开销比线程大在了哪里?
不知你在面试中是否遇到过这样的问题,题目很短,看似简单,但在回答时又感觉有点吃力?比如下面这两个问题:
进程内部都有哪些数据?
为什么创建进程的成本很高?
这样的问题确实不好回答,除非你真正理解了进程和线程的原理,否则很容易掉入面试大坑。本讲,我将带你一起探究问题背后的原理,围绕面试题展开理论与实践知识的学习。通过本讲的学习,希望你可以真正理解进程和线程原理,从容应对面试。
进程和线程
进程(Process),顾名思义就是正在执行的应用程序,是软件的执行副本。而线程是轻量级的进程。
进程是分配资源的基础单位。而线程很长一段时间被称作轻量级进程(Light Weighted Process),是程序执行的基本单位。
在计算机刚刚诞生的年代,程序员拿着一个写好程序的闪存卡,插到机器里,然后电能推动芯片计算,芯片每次从闪存卡中读出一条指令,执行后接着读取下一条指令。闪存中的所有指令执行结束后,计算机就关机。
轻量级进程
线程设计出来后,因为只被分配了计算资源(CPU),因此被称为轻量级进程。被分配的方式,就是由操作系统调度线程。操作系统创建一个进程后,进程的入口程序被分配到了一个主线程执行,这样看上去操作系统是在调度进程,其实是调度进程中的线程。
这种被操作系统直接调度的线程,我们也成为内核级线程。另外,有的程序语言或者应用,用户(程序员)自己还实现了线程。相当于操作系统调度主线程,主线程的程序用算法实现子线程,这种情况我们称为用户级线程。Linux 的 PThread API 就是用户级线程,KThread API 则是内核级线程。
分时和调度
因为通常机器中 CPU 核心数量少(从几个到几十个)、进程&线程数量很多(从几十到几百甚至更多),你可以类比为发动机少,而机器多,因此进程们在操作系统中只能排着队一个个执行。每个进程在执行时都会获得操作系统分配的一个时间片段,如果超出这个时间,就会轮到下一个进程(线程)执行。再强调一下,现代操作系统都是直接调度线程,不会调度进程。
分配时间片段
如下图所示,进程 1 需要 2 个时间片段,进程 2 只有 1 个时间片段,进程 3 需要 3 个时间片段。因此当进程 1 执行到一半时,会先挂起,然后进程 2 开始执行;进程 2 一次可以执行完,然后进程 3 开始执行,不过进程 3 一次执行不完,在执行了 1 个时间片段后,进程 1 开始执行;就这样如此周而复始。这个就是分时技术。
下面这张图更加直观一些,进程 P1 先执行一个时间片段,然后进程 P2 开始执行一个时间片段, 然后进程 P3,然后进程 P4……
注意,上面的两张图是以进程为单位演示,如果换成线程,操作系统依旧是这么处理。
进程和线程的状态
一个进程(线程)运行的过程,会经历以下 3 个状态:
进程(线程)创建后,就开始排队,此时它会处在“就绪”(Ready)状态;
当轮到该进程(线程)执行时,会变成“运行”(Running)状态;
当一个进程(线程)将操作系统分配的时间片段用完后,会回到“就绪”(Ready)状态。
我这里一直用进程(线程)是因为旧的操作系统调度进程,没有线程;现代操作系统调度线程。
有时候一个进程(线程)会等待磁盘读取数据,或者等待打印机响应,此时进程自己会进入“阻塞”(Block)状态。
因为这时计算机的响应不能马上给出来,而是需要等待磁盘、打印机处理完成后,通过中断通知 CPU,然后 CPU 再执行一小段中断控制程序,将控制权转给操作系统,操作系统再将原来阻塞的进程(线程)置为“就绪”(Ready)状态重新排队。
而且,一旦一个进程(线程)进入阻塞状态,这个进程(线程)此时就没有事情做了,但又不能让它重新排队(因为需要等待中断),所以进程(线程)中需要增加一个“阻塞”(Block)状态。
注意,因为一个处于“就绪”(Ready)的进程(线程)还在排队,所以进程(线程)内的程序无法执行,也就是不会触发读取磁盘数据的操作,这时,“就绪”(Ready)状态无法变成阻塞的状态,因此下图中没有从就绪到阻塞的箭头。
而处于“阻塞”(Block)状态的进程(线程)如果收到磁盘读取完的数据,它又需要重新排队,所以它也不能直接回到“运行”(Running)状态,因此下图中没有从阻塞态到运行态的箭头。
相关文章
- [Qt教程] 第39篇 网络(九)进程和线程
- 假期(进程、线程、协程)
- 什么是进程?什么是线程?进程和线程之间的区别是什么?
- 进程隐藏与进程保护(SSDT Hook 实现)(一)
- 26、进程和线程之间的关系
- 查看端口号占用,并且杀掉占用端口的进程
- 【刷题】线程与进程 & 线程池
- 【python】进程与线程
- Windows和Linux下如何查看端口被哪个进程占用
- 深入浅析python中的多进程、多线程、协程
- 使用进程名禁止程序运行多次
- Linux获取进程执行时间
- 【刷题】线程与进程 & 线程池
- 进程与线程的一个简单解释
- 常见Java面试题 线程和进程的区别?
- Qt进程和线程之一:运行一个进程和进程间通信
- 进程、线程和协程的关系与区别
- concurrent.futures模块实现线程池或进程池,大幅提升CPU处理速度
- 【Python 八股文】- 进程、线程、协程
- 什么是计算机程序?操作系统、指令、进程、线程等
- 【Android 逆向】Android 进程注入工具开发 ( Visual Studio 开发 Android NDK 应用 | 使用 Makefile 构建 Android 平台 NDK 应用 )
- 【Android 进程保活】oom_adj 值 ( 简介 | 查询进程 PID | 根据进程 PID 查询 oom_adj 值 )
- Linux查看端口、进程情况及kill进程
- Java并发编程:进程和线程之由来
- 多CPU && 多核CPU | 多进程 && 多线程 | 并行 && 并发
- 23 openEuler管理进程-查看进程
- Linux怎么强制关闭docker 关闭某个进程 查看某个进程 关闭程序 关闭进程
- windows下通过net user add和powershell添加用户,sysmon仅仅采集到进程,而在windows安全日志可以看到账户添加信息