1. 进程
1.1 进程的定义与特征
(1)进程是什么?
进程是处于
执行过程
的程序,是系统分配资源的一个基本单位。
(2)进程的组成
进程由
PCB、程序段和数据段
组成。
(3)进程的特征
(4)PCB
进程中最重要的就是
PCB
。
1.2 进程的状态
进程的相关状态:
创建状态(new) :进程正在被创建,尚未到就绪状态。
就绪状态(ready) :进程已处于准备运行状态,即进程获得了除了处理器之外的一切所需资源,一旦得到处理器资源(处理器分配的时间片)即可运行。
运行状态(running) :进程正在处理器上上运行(单核 CPU 下任意时刻只有一个进程处于运行状态)。
阻塞状态(waiting) :又称为等待状态,进程正在等待某一事件而暂停运行如等待某资源为可用或等待 IO 操作完成。即使处理器空闲,该进程也不能运行。
结束状态(terminated) :进程正在从系统中消失。可能是进程正常结束或其他原因中断退出运行。
1.3 原语实现对进程的控制
(1)什么是进程控制?
进程控制就是
实现进程状态的转换
。
(2)什么是原语?
原语是一种特殊的程序,它具有“
执行时必须是一气呵成的
”。
(3)原语为什么用来实现进程的控制?
主要是因为原语的具有
执行时必须是一气呵成的
。
(4)相关的原语
进程的创建
进程的终止
进程的阻塞
进程的唤醒
进程的切换
1.4 进程之间的通信
(1)什么是进程的通信?
进程之间进行信息交换
,进程是操作系统进行资源分配的基本单位
。
(2)进程间的通信方式:
1. 管道/匿名管道(Pipes) :用于具有亲缘关系的父子进程间或者兄弟进程之间的通信。
2. 有名管道(Names Pipes) : 匿名管道由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道。有名管道严格遵循 先进先出(first in first out)。有名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
3. 信号(Signal) :信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生;
4. 消息队列(Message Queuing) :消息队列是消息的链表,具有特定的格式,存放在内存中并由消息队列标识符标识。管道和消息队列的通信数据都是先进先出的原则。与管道(无名管道:只存在于内存中的文件;命名管道:存在于实际的磁盘介质或者文件系统)不同的是消息队列存放在内核中,只有在内核重启(即,操作系统重启)或者显示地删除一个消息队列时,该消息队列才会被真正的删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比 FIFO 更有优势。消息队列克服了信号承载信息量少,管道只能承载无格式字 节流以及缓冲区大小受限等缺。
5. 信号量(Semaphores) :信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。这种通信方式主要用于解决与同步相关的问题并避免竞争条件。
6. 共享内存(Shared memory) :使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。可以说这是最有用的进程间通信方式。
7. 套接字(Sockets) : 此方法主要用于在客户端和服务器之间通过网络进行通信。套接字是支持 TCP/IP 的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
1.5 多线程模型
(1)什么是线程?
线程是轻量级进程
,是系统执行、处理机调度的基本单位
。
(2)为什么要引入线程?
为了
增加并发度
,减少并发带来的开销。
(3)线程的实现方式
线程的实现分为两类:用户级线程(User-Level Thread,UTL)
和内核级线程(Kernel-Level Thread, KTL)
。 内核级线程又称 内核支持的线程。
(4)线程间的通信方式
1. 互斥量(Mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如 Java 中的 synchronized 关键词和各种 Lock 都是这种机制。
2. 信号量(Semphares) :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量
3. 事件(Event) :Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操
(5)多线程模型
1. 多对一模型
2. 一对一模型
3. 多对多模型
2. 处理机调度
2.1 处理机调度的概念与层次
(1)处理机调度的基本概念:
按某一种算法选择进程将处理机分配给它,本质就是
分配处理机给进程
。
(2)调度的三个层次
2.2 进程调度的时机与方式
(1)什么时候进行进程调度?
- 进程正常终止,
主动放弃
处理机- 分给进程的时间片使用完了,进程
被动放弃
处理机。
(2)什么时候不能进行进程调度?
(2)进程的剥夺方式
- 所谓进程调度方式,是指当某个进程正在处理机上执行时,若有某个更为重要或紧迫的进程需要处理,即有优先权更高的进程进入就绪队列,此时应如何分配处理机。
(3)进程的切换
2.3进程调度的相关算法
1. 先到先服务(FCFS)调度算法 : 从就绪队列中选择一个最先进入该队列的进程为之分配资源
,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
2. 短作业优先(SJF)的调度算法 : 从就绪队列中选出一个估计运行时间最短的进程为之分配资源
,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
3. 时间片轮转调度算法 : 时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法,又称 RR(Round robin)调度。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间
。
4. 多级反馈队列调度算法 :前面介绍的几种进程调度的算法都有一定的局限性。如短进程优先的调度算法,仅照顾了短进程而忽略了长进程 。多级反馈队列调度算法既能使高优先级的作业得到响应又能使短作业(进程)迅速完成
。,因而它是目前被公认的一种较好的进程调度算法,UNIX 操作系统采取的便是这种调度算法。
5. 优先级调度 : 为每个流程分配优先级,首先执行具有最高优先级的进程
,依此类推。具有相同优先级的进程以 FCFS 方式执行。可以根据内存要求,时间要求或任何其他资源要求来确定优先级。
3. 进程的同步与互斥
3.1 进程同步与互斥的基本概念
(1)进程同步
进程同步又称
直接制约关系
(2)进程互斥
1. 进程互斥又称间接制约关系
2. 当一个进程对临界资源进行访问时,其他进程不能对该临界资源进行访问,必须等待占有该临界资源的进程释放该临界资源
,其他进程才能对其进行访问。
(3)为了禁止两个进程同时访问临界资源,需要满足以下规则
3.2 进程互斥的软硬件实现方法
(1)单标志法
(2)双标志先检查法
(3)双标志后检查法
(4)Peterson算法
3.3 信号量机制
(1)什么时信号量机制?
(2)整型信号量机制
(3)记录型信号量机制
(4)信号量机制实现进程互斥
(5)信号量机制实现进程同步
- 想象一下四则运算的顺序,加减乘除;
- 要想理解这一部分知识,必须知道P、V操作的内部实现原理
(6)信号量机制实现进程前驱
3.4 管程
(1)为什么引入管程?
引入管程的原因是为了
实现进程的同步与互斥
。
(2)管程的组成和特征
(3)Java中类似于管程的机制
个人认为Java中的
锁机制和同步器
与管程的原理十分相似。
package com.xiao.test.sync;
//第一步:创建资源类,设置相关的属性和操作方法
class Ticket{
//票数
private int number = 30;
//使用synchronized实现并发操作
//买票
public synchronized void sale(){
if(number > 0){
System.out.println(Thread.currentThread().getName() + " 卖出: " + (number --) + " 还剩:" + number);
}
}
}
public class saleTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(()->{
for(int i = 1; i <= 40; i ++){
ticket.sale();
}
},"AA").start();
new Thread(()->{
for(int i = 1; i <= 40; i ++){
ticket.sale();
}
},"BB").start();
new Thread(()->{
for(int i = 1; i <= 40; i ++){
ticket.sale();
}
},"CC").start();
}
}
synchronized
为独占锁
,且是重量级锁
。当一个线程 获取到该锁, 才有权限访问它所修饰的代码。只有占有 该锁的线程释放了该锁之后 其他线程才能获取该锁进行对相应代码的执行。
4. 死锁
1. 什么是死锁?
线程死锁描述的是这样一种情况:多个线程同时被阻塞
,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞
,因此程序不可能正常终止。
2. 产生死锁的条件
1. 互斥条件:该资源任意一个时刻只由一个线程占用。
2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3. 不剥夺条件:线程已获得的资源在未使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
3. 如何预防死锁?
1. 破坏请求与保持条件 :一次性申请所有的资源。
2. 破坏不剥夺条件 :占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
3. 破坏循环等待条件 :靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。
4. 如何避免死锁?
避免死锁就是在资源分配时,借助于
算法(比如银行家算法)
对资源分配进行计算评估,使其进入安全状态。