靠临界区保护信号量,靠信号量实现进程之间的同步
为什么要保护信号量
温故知新:什么是信号量
信号量就是资源的充裕度
:通过对这个量的访问和修改,让多进程有序推进
注:
信号量不是资源数量
,因为信号量可以为-3,但是能说数量为-3吗?不能。信号量只能说代表充裕度,
为正,表明资源充足,有n个资源
为负,表明资源匮乏,还少n个资源(有n个线程因资源匮乏而阻塞)
为什么要保护信号量
多线程请求资源时,程序需要根据 资源充裕度
决定是否予以放行(是否堵塞)。
那么必要的前提:就是保证资源充裕度
这个共享的变量
一定要被正确的修改。
什么是临界区
临界区就是一次只允许一个进程进入的那段代码
使用什么方法保护信号量,从而实现临界区
注:信号量和临界区的关系:信号量的修改代码 就是临界区
临界区代码的保护原则
互斥进入
一个进程在临界区中执行,就不在允许其他进程进入临界区
有空让进
临界区空闲时,一定要允许其他的进程进入
有限等待
一个进程从发出进入临界区请求开始,到进入临界区,不能无限等待
整体思路
在进入区和退出区分别写一些代码(临界区保护代码
),保证临界区一次只能被一个进程访问
怎么保护信号量
整体思路
具体实现
Perterson算法
只能用于两个进程之间的同步
从已经声明要修改信号量的进程中选取一个进程的方法:针对全局变量的退让机制
面包店算法
// 变量说明:
// i 表示当前进程PID
// j 表示当前迭代到的进程PID
// choosing[i] 表示当前进程i 是否正在 【声明修改信号量】, 默认值为false
// number[i] 表示当前进程i的排队号, number[i] > 0:表示 【已经声明要修改信号量 】。默认值为0
process(i) {
while (true) {
// 当前进程i正在 【声明修改信号量】
choosing[i] = true;
// number为上一个已发放的排队号加1
number[i] = 1 + max(number[1], number[2], ..., number[n-1]);
// 当前进程i 【声明修改信号量】 完毕
choosing[i] = false;
// 迭代所有进程
for (j = 0; j < n; j++) {
// 若当前迭代到的进程j正在【声明修改信号量】, 则等待其声明完毕
while(choosing[j]);
// 同时满足以下两个条件,一直空转:
// a、存在其他进程 【已经声明修改信号量 】
// b、选中的进程不是自己
// number[j] != 0:存在其他进程j 【已经声明修改信号量 】
// (number[j], j) < (number[i], i):选中幸运线程,规则:选中号码最小的 ,如果号码一样的,则选择 最先请求的
while (number[j] != 0 && (number[j], j) < (number[i], i));
}
// 临界区代码
// 当前线程【声明不再修改信号量】
number[i] = 0;
}
}
从已经声明要修改信号量的进程中选取一个进程的方法:编号机制