1.进程同步的概念
在多道程序程序环境下,进程并发执行时,不同进程之间存在不同相互制约的关系;
引入进程同步,协调了进程之间的相互制约关系;
1)临界资源
一次只允许一个进程使用的资源,即临界资源,例:共享变量、共享数据结构、打印设备等;
临界区访问的四个部分:1)进入区;2)临界区;3)推出区;3)剩余区;
2)同步
同步亦是直接制约关系,源于进程之间的相互协作进程之间在某种任务中,协调工作次序并等待、传递信息的制约关系;
注:同步与异步,同步即在一条路上大家先后走,异步即大家各自走不一样的路两路不影响;
3)互斥
互斥是相对于临界资源的进程排斥关系,一个进程在使用临界资源时,另一进程需等待,当前占用临界资源进程退出使用后,才能访问使用临界资源;
互斥原则:
1)空闲让进,临界区空间,允许一个进程进入;
2)忙则等待,以有进程在临界区,其他进程等待;
3)有限等待,等待进程等待时间有限;
4)让权等待,进程不进入临界区,释放处理去,防止“忙等”进程;针对while循环等待;
2.临界区的互斥方法
1)软件实现
1)单标志法,
算法思想:进程与进程之前传递让步标志访问临界资源;
缺点,违反空闲让进原则
2)双标志法先检测 和 双标志法后检测
双标志先检测,先检查,再上锁,检查,锁为两个标志
双标志先检测法违反忙则等待原则
双标志后检测法,先上锁,再检查;
双标志后检测法违反空闲让进、有限等待原则,会导致“饥饿”现象;
3)The algorithm of Peterson,皮特森算法
算法思想:结合单标志法和双标志法,有争取、有让步;
解决了两进程互斥防卫临界区,遵循了空闲进入、忙则等待、有限等待;
但为遵循让权等待,当进程长时间堵在while循环不释放处理器;
2)硬件实现
1)中断屏蔽法;2)硬件指令法(Test-and-Set指令或Swap指令)
软件实现互斥总结图:
硬件实现互斥总结图:
3.信号量机制
前面的算法都不能实现让权等待原则
使用PV操作原句对临界资源的同步、互斥访问;wait(S)、signal(S);
1.整型信号量
wait(S){ while(S<=0);//资源不够等待; S--;//占用一个资源,信号量减1 } signal(S){ S++;//资源释放,信号量+1; }
2.记录型信号量
typedef struct{ int value;//信号量值,资源个数 struct process *L;//等待进程队列,可顺序可链式 }semaphore; void wait(semaphore S){ S.value--;//先占用一个资源,只有最后一个资源时,--后value=0; if(S.value<0){//资源消耗完;--后value=-1; add current_process to S.L; block(S,L);//阻塞 } } void wait(semaphore S){ S,value++; if(S.value<=0){//value=0时资源还有1个; remove a process P from S.L;//取出一个等待进程; wakeup(P);//唤醒该进程; } } //block()、wakeup()实现对进程的让权等待原则
3.进程的互斥
semaphore mutex=1;//互斥型号量设置为1,默认信号量为记录型信号量 P1(){ ....; P(mutex);//matux--;占用唯一资源 临界区; V(mutex);//释放资源,并唤醒等待进程; ....; } P2(){ ....; P(mutex);//matux--;占用唯一资源 临界区; V(mutex);//释放资源,并唤醒等待进程; ....; }
4.进程的同步
//确定x操作一定再y操作之前,既满足同步; semaphore S=0;//设置同步信号量为0; P1(){ ....; x;//x操作 V(S);//S++,信号量不为0,P(V)不用等待; ....; } P2(){ ....; P(S);//若信号量>0,不要等待即x操作已执行完;若信号量为0则x未操作完,进程阻塞,等待被唤醒; y;//y操作 ....; }
进程的同步、互斥
4.管程
对进程同步互斥的操作进行封装的产物;
5.经典同步问题
1)生产者消费者问题(同步、互斥)
问题描述:多个相同生产者和多个相同消费者共享一个大小为n的缓冲区,缓冲区有空时,生产者才能生产,缓冲区有产品时,消费者才能消费,否则等待;缓冲区为临界资源,只允许一个生产者或消费者对其生产或消费;
同步问题:1)缓冲区有空时,生产者才能生产 ;2)缓冲区有产品时,消费者才能消费
互斥问题:缓冲区为临界资源,只允许一个生产者或消费者对其生产或消费;
semaphore empty=n;//缓冲区剩余数量,初始为缓冲区大小 semaphore full=0;//缓冲区生产的产品个数,即占用的个数,初始为0,空闲,未有产品; semaphore mutex=1;//互斥信号量 producer(){ while(1){ 生产一个产品; P(empty);//占用一个 P(mutex);//占用互斥信号量,其他所有P(mutex)等待; 放入产品;//对临界区的操作,用PV操作互斥包裹,只有一个进程对它操作; V(mutex);//释放信号量,唤醒一个P(mutex)等待进程 V(full);//告诉生产者,已生产一个产品,有等待消费进程则唤醒,消费者进程为就绪态; } } consumer(){ while(1){ P(full);//缓冲区中产品-1,申请消费 P(mutex); 取出产品;//对临界区的操作,用PV操作互斥包裹 V(mutex); V(empty);//告诉消费者,已消费一个产品,empty空闲空间+1,有等待生产进程则唤醒; 消费一个产品; } }
注:
实现互斥与同步之间的两个P操作的先后顺序会造成死锁现象,两个进程都在等待对方释放互斥信号量;
但V操作的前后顺序没有严重影响;
复杂的生产者消费者问题(同步、可不需互斥)
不同生产者和不同消费者问题:
一个盘子,只允许放一个水果;父亲只能放苹果,妈妈只能放橘子,女儿只等吃苹果,儿子只等吃橘子;爸爸或妈妈只能在牌子空时才能放,儿子女儿盘子有自己想要的水果才能取走;
一个互斥问题:
对盘子的放入水果和取走水果;//临界区的大小为1;
三个同步问题:
父亲放入苹果事件和女儿取走苹果事件的先后顺序;
母亲放入橘子事件和儿子取走橘子事件的先后顺序;
女儿取走苹果事件触发盘子为空,则需要父亲或母亲放入;
儿子取走橘子事件触发盘子为空,需要父亲或母亲放入;
将问题事件的先后顺序描述为前驱图(前V后P);
[外链图片转存失败(img-Vgeb5ytL-1569478183236)(C:\Users\lin\AppData\Roaming\Typora\typora-user-images\1569304505753.png)]
semphore plate=1,//共享区域大小 apple=0, orange=0, //mutex=1;//共享区域大小为1则当前只有一个进程占用,若逻辑符合则不需要互斥遍历;这里可以不需要,即用PV操作包裹放入盘子,盘中取走; father(){ while(1){ 弄一个苹果; P(plate); //P(mutex);//之后进程省略 放入盘子 //V(mutex); V(apple); } } mather(){ while(1){ 弄一个橘子; P(plate) 放入盘子; V(orange); } } daughter(){ while(1){ P(apple);//等待苹果 盘中取走苹果; V(plate);//唤醒等待盘子的爸爸或妈妈 eat...; } } son(){ while(1){ P(orange);//等待橘子 盘中取走橘子; V(plate);//唤醒等待盘子的爸爸或妈妈; eat...; } }
2)读写者问题(互斥)
经典复杂互斥问题;
问题描述:多读写者进程并发执行(写,是往文件里加,读,只是读不改变文件大小,不是消费),共享一个文件,当两个或以上的读进程同时读不会产生副作用,但若某个写进程和其他写进程同时访问共享数据时可导致数据的不一致;故应满足如下要求:
1)允许多个读者同时读;2)只允许一个写者写;3)写时不允许读;4)读时允许写;
分析:
互斥关系
1)写者与写者互斥;2)读者与写者互斥;3)读者和读者不存在互斥关系;
隐含读写之间的优先或公平问题
读者优先,写者可能长期处于饥饿状态;
写进程优先,即让当前读者不再增加,等待原读进程读完,执行写进程;这样的写进程优先是相对而言的,也称读写公平法;
3)哲学家进餐问题
哲学家进餐的问题关键在于解决进程死锁;
这些进程只存在互斥关系,但与之前其他问题的互斥关系不同的是,哲学家问题进程需要同时持有两个临界资源,才能执行想要执行的操作,因此就会存在“死锁”的问题;
注:死锁,进程需要两个或以上的资源时可能会产生都有部分资源但都需等待对方释放资源,造成都等待的死锁现象;
参考哲学家进餐问题可以解决死锁的三种思路;
总结:
1)为什么要引入进程同步的概念?
在多道程序程序环境下,进程并发执行时,不同进程之间存在不同相互制约的关系;
引入进程同步,协调了进程之间的相互制约关系;
2)同步、互斥是什么?
同步时是进程之间在某种任务中,协调工作次序并等待、传递信息的制约关系;
互斥是相对于临界资源的进程排斥关系,一个进程在使用临界资源时,另一进程需等待,当前占用临界资源进程退出使用后,才能访问使用临界资源;
3)怎么产生死锁现象呢?
进程在执行过程中占有一些资源,且都需要等待对方释放资源的执行,产生一直互相等待的现象,即死锁;