17-信号量实现互斥、同步、前驱关系
信号量实现互斥、同步、前驱关系
信号量机制实现进程互斥
- 分析并发进程的关键活动,划定临界区(如:对临界资源打印机的访问就应该放在临界区)
- 设置互斥信号量mutex,初值为1
- 在临界区前执行P(mutex)
- 在临界区后执行V(mutex)
代码示例
/*信号量机制实现互斥*/
semaphor 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;
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了
信号量机制实现前驱关系
进程P1有句代码S1,P2中有句代码S2,P3…P6中有句代码S6,这些代码可以按照如下前驱图所示关系来执行。
其实每一对前驱关系都是一个进程同步的问题(需要保证一前以后的操作)
因此:
- 要为每一对前驱关系各设置一个同步变量
- 在“前操作”之后对相应同步变量执行V操作
- 在“后操作”之前对相应同步变量执行P操作