semaphore mutex=1;
P1(){
...
P(mutex)
临界区代码段...
V(mutex)
...
}
P2(){
...
P(mutex)
临界区代码段...
V(mutex)
...
}
进程同步的目的在于让各个本来异步并发的进程按要求有序推进
P1(){
代码1;
代码2;
代码3;
}
P2(){
代码4;
代码5;
代码6;
}
例如,在上面的P1和P2进程中,由于异步性导致程序执行顺序并不确定,但我们必须保证代码1和代码2在代码4之前执行,此时就需要使用进程同步机制实现
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,这些代码要求按如下前驱图所示的顺序执行
其实每一对前驱关系都是一个进程同步问题(需要保证一前一后的操作),所以
不难看出,前驱关系本质上还是更复杂的进程同步问题