OS:进程&线程、死锁
1、进程 & 线程
1.1、联系与区别
| 进程 | 线程 | |
|---|---|---|
| 含义 | 一个在内存中运行的应用程序 | 进程的一个执行任务 |
| 包含关系 | 一个进程有若干个线程,至少包含一个线程 | 进程的一部分,相当于只有一个任务的进程(也称轻权进程、轻量级进程) |
| 根本区别 | 操作系统资源分配的基本单位 | 处理器任务调度和执行的基本单位 |
| 资源开销 | 每个进程都有独立的代码和数据空间(程序上下文),上下文切换的开销大 | 同一类线程共享代码和数据空间,每个线程有独立的栈区和程序计数器,上下文切换的开销小 |
| 内存分配 | 不同进程间的地址空间和资源相互独立 | 同一进程的线程共享本进程的地址空间和资源 |
| 影响关系 | 进程崩溃后,在保护模式下不影响其它进程 | 线程“崩溃”,可能导致整个进程崩溃。 (多进程比多线程健壮) |
| 执行过程 | 可独立执行,有程序运行的入口、顺序执行序列和程序出口 | 线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制 |
1.2、线程崩溃
线程“崩溃”时触发 segment fault 信号
系统的默认处理方式是终结该线程所在的进程,也可屏蔽信号。
- 不屏蔽信号:操作系统终止该线程所在的进程。
- 屏蔽信号:由线程的崩溃位置决定
- 线程独占区:不影响其它线程。
- 线程共享区:会的
Java 线程崩溃,JVM 自动释放相关的资源,不会导致进程崩溃。
1.3、线程状态
-
OS 层面:初始、可运行、运行、阻塞、终止。

-
Java Thread API:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED

2、锁的活跃性
- 死锁:多个进程在竞争资源或彼此通信而造成的阻塞。
- 饥饿:某个进程一直得不到资源。
2.1、资源类型
分类标准:可重用、可抢占。
2.1.1、重用性
- 可重用资源(永久)
- 可被多个进程多次使用(如硬件)。
- 一次只能分配给一个进程使用,其它线程必须等待资源释放。
- 数目:固定,进程无法创建或删除。
- 使用顺序:请求资源、使用资源、释放资源。
- 消耗性资源(临时)
- 进程在运行期间动态的创建和消耗。
- 数目:进程运行期间是可以不断变化(0 或多个)。
- 典例:进程间通信的消息。
- 创建:通常由生产者进程创建,放入该资源类的缓冲区。
- 消耗:通常由消费者进程消耗,进程可请求若干个资源并消耗,不再放回缓冲区。
2.1.2、抢占性
- 可抢占资源:被进程获取后,可被其他进程或系统抢占,不会引起死锁(如 CPU、主存)
- 不可抢占资源:被进程获取后,只能等进程本身释放资源(如打印机)
2.2、死锁
2.2.1、产生原因
- 竞争不可抢占资源(互斥)
- OS 中仅有一台打印机和输入设备,某一时刻进程 P1 使用打印机,P2 使用输入设备。
- 此时 P1 请求使用输入设备、P2 请求使用打印机,双方等待彼此的资源。
- 竞争可消耗资源(循环等待)
- 三个进程互相发送消息(可消耗资源)
- 进程 P1 接收 P3 的消息 m3,发送 m1 给 P2;P2 接收 P1 的m1,发送 m2 给 m3;P3 接收 P2 的 m2,发送 m3 给 m1。
- 若进程先发送再接收,OK。
- 若进程先接收再发送,死锁。
- 进程执行顺序:系统进入不安全状态。
2.2.2、特征(必要条件)
只要发生死锁,以下 4 个条件同时成立。
- 互斥:至少有一个资源非共享,同一时刻只有一个线程能使用。
- 不可剥夺:即不可抢占资源,资源只能在进程完成任务后主动释放。
- 请求与保持:进程占用至少一个资源,并等待另一个被其它进程占用的资源。
- 循环等待:存在进程资源的循环等待链(如进程 P1 等待 P2,P2 等待 P1)
2.2.3、处理
- 预防
- 避免
- 检测
- 接触
预防
设置限制条件,破坏产生死锁的 4 个必要条件。
- 互斥:无法破坏
- 不可剥夺:请求被另一个进程占有的资源被拒绝时,释放当前进程的资源、或抢占资源。
- 循环等待:有序资源分配法
避免
在资源的动态分配过程中,用某种方法防止系统进入不安全状态。
- 有序资源分配法:将资源统一编号,进程必须按编号顺序申请资源。
- 示例:操作系统中有一个 R1、R2 资源,分别编号为 1、2
- 进程必须按编号升序申请,即 R1 → R2,不能是 R2→ R1。
- 破坏循环等待的条件
- 银行家算法:允许进程动态申请资源,在资源分配前检查安全性。
- 拟分配资源给当前进程,计算剩余资源数量是否能满足下一进程的需求。
常用技术
- 加锁顺序:线程按一定的顺序加锁。
- 加锁时限:线程尝试获取锁时加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁。
- 死锁检测
检测
设置检测机构,及时检测死锁的发生。
解除
检测出死锁后,采取适当措施将进程从死锁状态中解脱出来。
- 资源剥夺:挂起某些死锁进程并剥夺资源,分配给其它死锁进程。
- 撤销进程:强制撤销部分或全部死锁进程并剥夺资源。
- 进程回退:设置还原点,让死锁进程回退到足以回避死锁,进程回退时自愿释放资源而不是被剥夺。