一、进程和线程
1. 什么是进程?为什么要有进程?
i. 简单解释什么是进程:正在运行的程序及其占用的资源(CPU,内存,系统资源等)叫做进程。
ii. 需要进程的原因:当软件需要运行,加载存在硬盘之中的程序代码到内存之中,CPU执行这些代码,并且运行期间调用各种如屏幕、键盘、网卡、声卡等硬件资源,当运行的程序非常多时候,免不了对这些计算机资源进程管理,并且操作系统还需要调用CPU分配给各个程序使用,让用户感觉程序在同时运行,不影响体验。所以,对于操作系统而言,系统会把每个运行中的程序封装成独立的实体,分配需要的资源,再根据调度算法切换执行,这个运行的程序及其占用的资源就叫进程了。需要进程就是为了方便操作系统更好地进行资源分配和系统调度。
2. 什么是线程?为什么要有线程?
i. 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
简单来讲,线程是进程的一条执行路径,再Unix系统下,通常叫做轻量化的进程。
ii. 在早期的操作系统中并没有线程的概念,进程是拥有资源和独立运行的最小单位,也是程序执行的最小单位。随着计算机行业发展,程序功能越来越复杂,在应用中需要同时发生着多种活动,把这些应用程序分解成更加小的顺序执行实体,并且这些执行实体可以共享进程的地址空间,共享文件代码、数据、内存空间等,让程序设计变得更加简单。
需要多线程还有一个重要的理由就是:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小。所以线程的创建、销毁、调度性能远远优于进程。
二、进程与线程的区别
从多个维度上对比
对比维度 | 进程 | 线程 |
---|---|---|
功能 | 进程是操作系统资源分配的基本单位 | 线程是任务调度和执行的基本单位 |
开销 | 每个进程都有独立的内存空间,存放代码和数据段等,程序之间的切换会有较大的开销 | 线程可以看做轻量级的进程,共享内存空间,每个线程都有自己独立的运行栈和程序计数器,线程之间切换的开销小 |
运行环境 | 在操作系统中能同时运行多个进程 | 而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行) |
创建销毁、切换过程 | 在创建新进程的时候,会将父进程的所有五大数据结构复制新的,形成自己新的内存空间数据,销毁、切换复杂,速度慢 | 而在创建新线程的时候,则是引用进程的五大数据结构数据,但是线程会有自己的私有数据、栈空间,销毁、切换简单、速度块 |
数据共享、同步 | 数据共享复杂,需要用IPC;数据是分开的,同步简单 | 因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂 |
可靠性 | 进程间不会互相影响 | 一个线程挂掉将导致整个进程挂掉 |
根据使用场景不同,选择多进程还是多线程
1)需要频繁创建销毁的优先用线程
2)需要进行大量计算的优先使用线程
3)强相关的处理用线程,弱相关的处理用进程
4)都满足需求的情况下,用你最熟悉、最拿手的方式
代码层面上看
上层关键代码
多进程 | 多线程 | |
---|---|---|
创建函数 | fork() | p_thread_create |
创建一个新的子进程,根据返回值进入不同的进程空间,子进程会复制一份父进程的代码 | 创建一个子线程,把自定义的线程主体也传递进去,注意确定需要的线程属性 | |
获取ID函数 | getpid()&getppid | pthread_self |
获取自己进程的PID & 获取父进程的PID | 获取自己线程的ID | |
库函数 | system() | |
快速创建一个进程执行相应的命令 | ||
锁 | pthread_mutex_*() | |
由于线程之间共享资源,多个线程访问存在临界资源,需要使用锁的概念,利用互斥锁相关的函数,是多线程之间更好访问操作临界资源 | ||
getrlimit() & setrlimit() | ||
解除多进程的限制的函数 |