信号量机制实现进程互斥
主要步骤
- 分析并发进程的关键活动,划定临界区(例如:对打印机等临界资源的访问就应放在临界区内)
- 设置互斥信号量,常命名为mutex,初值为1(因为一般情况下对临界区的访问同一时间只能存在一个进程)
- 在临界区之前执行P(mutex)
- 在临界区之后执行V(mutex)
示例
代码语言:javascript复制semaphore mutex=1;
P1(){
...
P(mutex)
临界区代码段...
V(mutex)
...
}
P2(){
...
P(mutex)
临界区代码段...
V(mutex)
...
}
注意
- 对不同的临界资源需要设置不同的互斥信号量(mutex1,mutex2)
- P,V操作必须成对出现,缺少P就不能保证临界资源的互斥访问,缺少V就会导致资源永远不被释放,等待进程永远不能唤醒
信号量机制实现进程同步
进程同步的目的在于让各个本来异步并发的进程按要求有序推进
代码语言:javascript复制P1(){
代码1;
代码2;
代码3;
}
P2(){
代码4;
代码5;
代码6;
}
例如,在上面的P1和P2进程中,由于异步性导致程序执行顺序并不确定,但我们必须保证代码1和代码2在代码4之前执行,此时就需要使用进程同步机制实现
用信号量实现进程同步的步骤
- 分析什么地方需要实现“同步关系”,即保证“一前一后”执行的两个操作
- 设置同步信号量:S,初值为0
- 在“必须先执行的操作”之后执行V(S)
- 在“必须后执行的操作”之前执行P(S)
示例
代码语言:javascript复制semaphore S=0; //初始化同步信号量,初值为0
P1(){
代码1;
代码2;
//代码1和代码2是必须先执行的操作
//所以在它们之后执行V(S)
V(S);
代码3;
}
P2(){
//代码4是必须后执行的操作
//所以在它前面执行P(S)
P(S);
代码4;
代码5;
代码6;
}
若先执行了P1进程,执行完代码1和代码2后,进行V操作,则信号量S 后S=1,之后执行P2进程时,执行P操作判断S=1>0所以表示有可用资源可以继续执行,S–后S=0,不会执行block原语被阻塞,可以继续往下执行代码4
若先执行P2进程,由于P操作判断S=0表示没有可用资源,所以执行block原语,主动请求阻塞P2进程,直到P1进程执行完代码1和代码2后到V操作发现S=-1表示等待队列中有进程在等待资源,所以其主动唤醒P2进程,P2进程得以继续执行代码4
信号量机制实现前驱关系
一共有六个进程P1,P2…P6,其中进程P1中有代码S1,P2中有代码S2,…P6中有代码S6,这些代码要求按如下前驱图所示的顺序执行
主要步骤
其实每一对前驱关系都是一个进程同步问题(需要保证一前一后的操作),所以
- 要为每一对前驱关系各设置一个同步变量
- 在“必须先执行操作”之后对相应同步变量执行V操作
- 在“必须后执行操作”之前对相应同步变量执行P操作
不难看出,前驱关系本质上还是更复杂的进程同步问题