文章目录
- 一、知识总览
- 二、知识点回顾
- 三、信号量机制实现进程互斥
- 四、信号量机制实现进程同步
- 五、信号量机制实现前驱关系
- 六、总结
一、知识总览
二、知识点回顾
整型信号量:用一个整数型的变量作为信号量,用来表示系统中某种资源的数量。
记录型信号量:用记录型整数结构表示的信号量。
(具体知识点讲解见(二十)操作系统-信号量机制)
三、信号量机制实现进程互斥
分析并发进程的关键活动,划定临界区(如:对临界资源打印机的访问就应放在临界区)
设置互斥信号量mutex,初值为1。在临界区之前执行P(mutex),在临界区之后执行V(mutex)。
/*信号量机制实现互斥*/
semaphore mutex=1; //初始化信号量
P1(){
...
P(mutex); //使用临界资源前需要加锁
临界区代码段...
v(mutex); //使用临界资源后需要解锁
...
}
P2( ){
...
P(mutex);
临界区代码段...
v(mutex);
...
}
注意:
对不同的临界资源需要设置不同的互斥信号量。
P、V操作必须成对出现。缺少P(mutex)就不能保证临界资源的互斥访问。缺少V(mutex)会导致资源永不被释放,等待进程永不被唤醒。
四、信号量机制实现进程同步
进程同步:要让各并发进程按要求有序地推进。(详细可见文章(十七)操作系统-进程同步、互斥)
信号量机制实现同步:
- 设置同步信号量s,初始为0。
- 在“前操作”之后执行v(S)。
- 在“后操作”之前执行P(S)。
/*信号量机制实现同步*/
semaphore S=0; //初始化同步信号量,初始值为0
P1( ){
代码1;
代码2;
v(S);
代码3;
}
P2(){
P(S);
代码4;
代码5;
代码6;
}
若先执行到v(S)操作,则S++后S=1。之后当执行到P(S)操作时,由于S=1,表示有可用资源,会执行S–,S的值变回0,P2进程不会执行block原语,而是继续往下执行代码4。
若先执行到P(S)操作,由于S=0,S–后S = -1,表示此时没有可用资源,因此P操作中会执行block原语,主动请求阻塞。之后当执行完代码2,继而执行V(S)操作,S++,使S变回0,由于此时有进程在该信号量对应的阻塞队列中,因此会在V操作中执行wakeup原语,唤醒P2进程。这样P2就可以继续执行代码4了。以此保证了代码4一定是在代码2之后执行。
五、信号量机制实现前驱关系
进程P1中有句代码S1,P2中有句代码S2…P3… P6中有句代码S6。这些代码要求按如下前驱图所示的顺序来执行:
- 其实每一对前驱关系都是一个进程同步问题(需要保证一前一后的操作),因此,要为每一对前驱关系各设置一个同步变量。
- 在“前操作”之后对相应的同步变量执行v操作。
- 在“后操作”之前对相应的同步变量执行Р操作。
- 即代码如下图
六、总结
除了互斥、同步问题外,还会考察有多个资源的问题,有多少资源就把信号量初值设为多少。申请资源时进行P操作,释放资源时进行V操作即可。