操作系统知识点---第 4 章 进程同步与死锁(未补完)

操作系统目录:
第 1 章 计算机系统概述
进程管理(2~4)
第 2 章 进程与线程
第 3 章 处理机调度
第 4 章 进程同步与死锁
第 5 章 内存管理
第 6 章 文件管理
第 7 章 I/O管理

1. 进程同步、进程互斥

  1. 什么是进程同步

并发执行两个进程时,现在要求一号指令必须在二号指令之前执行。例如写数据必须发生在读数据之前。

并发性带来了异步性,有时需要通过进程同步解决这种异步问题。有的进程之间需要相互配合地完成工作,各进程的工作推进需要遵循一定的先后顺序。
2. 什么是进行互斥

临界资源:一个时间段内只允许一个进程使用的资源。

临界资源的访问,需要互斥的进行。即同一时间段内只能允许一个进程访问该资源。
3. 对临界资源的互斥访问,可以分为如下四个部分:

do {
	entry section;	//进入区:检查是否可进入临界区,若可进入,需要“上锁”
	critical section;	//临界区:访问临界资源的那段代码
	exit section;	//退出区:负责“解锁”
	remainder section;	//剩余区:做其他处理
} while(true)
  1. 对临界资源的互斥访问,遵循以下原则:
  • 空闲让进:临界区空闲时,应允许一个进程访问
  • 忙则等待:临界区正在被访问时,其他试图访问的进程需要等待
  • 有限等待:要在有限时间内进入临界区,保证不会饥饿
  • 让权等待:进不了临界区的进程,要释放处理机,防止进程忙等待

2. 进程互斥的软件实现方法

  1. 单标志法
    每个进程进入临界区的权限只能被另一个进程赋予
    在进入区只做“检查”,不“上锁”
    在退出区,把临界区的使用权转交给另一个进程(相当于在退出区给另一个进程“解锁”,给自己“上锁”)
int turn = 0;	//turn 表示当前允许进入临界区的进程号

P0进程:
while (turn != 0);		//1⃣️进入区
critical section;		//2⃣️临界区
turn = 1;				//3⃣️退出区
remainder section;		//4⃣️剩余区

P1进程:
while( turn != 1);		//5⃣️进入区
critical section;		//6⃣️临界区
turn = 0;				//7⃣️退出区
remainder section;		//8⃣️剩余区
  • turn的初值为0,即刚开始只允许0号进程进入临界区。
  • P1先上处理机运行,则会一直卡在5⃣️(因为while的循环条件一直被满足)。直到P1的时间片用完,发生调度,切换P0上处理机。
  • P0进程,因为while循环条件不被满足,所以会跳出循环,进入临界区,P0可以正常访问临界区。
  • P0访问临界区期间即使切换回P1P1依然会卡在5⃣️(因为turn没有变)
  • 只有P0在退出区将turn改为1后,P1才能进入临界区。
    问题:不遵循“空闲让进”
  1. 双标执先检查
    在进入区先“检查”后上锁,退出区“解锁”
bool flag[2];	//表示进入临界区意愿的数组
flag[0] = false;
flag[1] = false;//刚开始设置为两个进程都不想进入临界区

P0 进程:
while (flag[1]);
flag[0] = true;
critical section;
flag[0] = false;
remainder section;

P1 进程:
while (flag[0]);	//如果此时P0想进入临界区,P1就一直循环等待
flag[1] = true;		//标记为 P1 进程想要进入临界区
critical section;	//访问临界区
flag[1] = false;	//访问完临界区,修改标记为 P1 为不想使用临界区
remainder section;	

问题:不遵循“忙则等待”
3. 双标志后检查法
在进入区,先“上锁”后“检查”,退出区“解锁”

bool flag[2];	//表示进入临界区意愿的数组
flag[0] = false;
flag[1] = false;	//刚开始设置为两个进程都不想进入临界区

P0 进程:
flag[0] = true;
while (flag[1]);
critical section;
flag[0] = false;
remainder section;

P1 进程:
flag[1] = true;		//标记为 P1 进程想要进入临界区
while (flag[0]);	//如果P0也想进入临界区,则P1循环等待
critical section;	//访问临界区
flag[1] = false;	//访问完临界区,修改标记为 P1 不想使用临界区
remainder section;

问题:不遵循“空闲让进、有限等待原则”,可能导致饥饿
4. Peterson算法
在进入区“主动争取—主动谦让—检查对方是否想进、自己是否谦让”

bool flag[2];
int turn = 0;
P0 进程:
flag[0] = true;
turn = 1;
while (flag[1] && turn==1)
//进入区
critical section;
flag[0] = false;
remainder section;
P1进程:
flag[1] = true;		//表示自己想进入临界区
turn = 0;			//可以优先让对方进入临界区
while (flag[0] && turn==0);	//对方想进,且最后一次是自己“让梨”,那自己就循环等待
critical section;
flag[1] = false;	//访问完临界区,表示自己已经不想访问临界区了
remainder section;

问题:不遵循“让权等待”原则,会发生忙等

3.进程互斥的硬件实现方法

  1. 中断屏蔽
    利用“开/关中断指令”实现
···
关中断;
临界区;
开中断;
···

优点:简单高效
缺点:只适用于单处理机;只适用于操作系统内核进程
2. TestAndSet指令
TS指令,TestSandLock指令,TSL指令
old记录是否已被上锁;再将lock设为true
检查临界区是否已被上锁,若已上锁,则循环重复前几步

//lock 表示当前临界区是否被加锁,true表示已加锁,false表示未加锁
bool TestAndSet(bool *lock) {
	bool old;
	old = *lock;		//old用来存放lock 原来的值
	*lock = true;	//无论之前是否已加锁,都将lock设为true
	return old;
}

//使用 TSL 指令实现互斥的算法逻辑
while (TestAndSet (&lock));	//“上锁”并“检查”
临界区代码段...
lock = false;	//“解锁”
剩余区代码段...

优点:实现简单,适用于多处理机环境
缺点不满足让权等待
3. Swap指令
Exchange 指令、XCHG 指令

//Swap 指令的作用是交换两个变量的值
Swap (bool *a, bool *b) {
	bool temp;
	temp = *a;
	*a = *b;
	*b = temp;
}

//使用 Swap 指令实现互斥的算法逻辑
//lock 表示当前临界区是否被加锁
bool old = true;
while (old == true)	//临界区在之前为上锁状态
	Swap (&lock, &old);
临界区代码段...
lock = false;
剩余区代码段...

逻辑、优缺点与TSL相同。

4. 信号量机制

信号量机制:用户进程通过操作系统提供的一对原语来对信号量进行操作。
信号量:表示系统中某种资源的数量。
原语:是由关中断/开中断指令实现。
一对原语:简称为P、V操作。

  1. 整型信号量:
    1. 概念:用一个整数型的变量作为信号量,数值表示某种资源的数量。
    2. 整型信号量与普通整型变量的区别:对信号量只能执行:初始化、P、V三种操作
    3. 整型信号量存在的问题:不满足让权等待原则
      对整形信号量x,定义P操作及V操作原语如下:
P(x)
	{
		while(x<=0);
		x=x-1;
	}
V(x)
	{
		x = x+1;
	}
  1. 记录型信号量:用记录型数据结构表示的信号量。
    1. S.value 表示某种资源数,S.L 指向等待该资源的队列
    2. P 操作中,一定是S.value–,之后可能需要执行 block 原语
    3. V 操作中,一定是S.value++,之后可能需要执行 wakeup 原语
    4. 注意:要能够自己推断在什么条件下需要执行 block 或 wakeup
    5. 可以用记录型信号量实现系统资源的“申请”和释放
    6. 可以用记录型信号量实现进程互斥、进程同步

5. 用信号量实现进程互斥、同步

  • 信号量机制实现进程互斥
    1. 分析问题,划定临界区(如:对临界资源打印机的访问就应放在临界区)
    2. 设置互斥信号量 mutex,初值为1
    3. 临界区之前对信号量执行 P操作:P(mutex)
    4. 临界区之后对信号量执行 V操作:V(mutex)
  • 信号量机制实现进程同步
    1. 分析问题,找出哪里需要实现“一前一后”的同步关系
    2. 设置同步信号量,初始值为0
    3. “前操作”之后执行V操作
    4. “后操作”之前执行P操作
  • 实现进程的前驱关系:
    1. 分析问题,画出前驱图,把每一对前驱关系都看成一个同步问题
    2. 为每一对前驱关系设置同步信号量,初值为0
    3. 在每个“前操作”之后执行V操作
    4. 在每个“后操作”之后执行P操作
  • 注意:
    • 互斥问题,信号量初值为1
    • 同步问题,信号量初值为0
    • 前驱关系问题,本质上就是更复杂的同步问题
    • 除了互斥、同步问题外,还会考察有多少个资源的问题。有多少资源就把信号量初值设为多少。申请资源时进行P操作,释放资源时进行V操作。

6. 生产者-消费者问题

生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。
同步关系:缓冲区满时,生产者要等待消费者取走产品
同步关系:缓冲区空时(即没有产品时),消费者要等待生产者放入产品
互斥关系:缓冲区是临界资源,各进程必须互斥地访问。

信号量机制可实现互斥、同步、对一类系统资源的申请和释放。

7. 多生产者-多消费者问题

8. 吸烟者问题

9. 读者-写者问题

10. 哲学家进餐问题

11. 管程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值