一.信号量机制实现进程互斥
1.分析并发进程的关键活动,划定临界区
2.设置互斥信号量木特性,初值为1
3.在临界区之前执行P(mutex)
4.在临界区之后执行V(mutex)
semaphore mutex = 1; //初始化信号量
P1(){
...
P(mutex); //使用临界资源前需要加锁
临界区代码段...
V(mutex); //使用临界资源后需要解锁
...
}
P2(){
...
P(mutex); //使用临界资源前需要加锁
临界区代码段...
V(mutex); //使用临界资源后需要解锁
...}
二.信号量机制实现同步
1.分析什么地方需要实现"同步关系",即保证”一前一后“执行的两个操作(或两句代码)
2.设置同步信号量S,初始为0
3.在”前操作“之后执行V(S)
4.在”后操作“之前执行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,由于此时有进程在该信号量对应的阻塞队列中
三.生产者消费者问题
系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者金恒每次从缓冲区取出一个产品并使用。生产者、消费者共享一个初始为空、大小为n的缓冲区。
只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。(同步关系)
只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。(同步关系)
缓冲区是临界资源,各进程必须互斥访问。(互斥关系)
semaphore mutex = 1; //互斥信号量,实现对缓冲区的互斥访问
sempaphore empty = n; //同步信号量,表示空闲缓冲区的数量
sempaphore full = 0; //同步信号量,表示产品的数量,也即非空缓冲区的数量
producer(){
while(1){
生产一个产品;
P(empty);
P(mutex);
把产品放入缓冲区;
V(mutex);
V(full);
}
}
consumer(){
while(1){
P(full);
P(mutex);
从缓冲区中取出一个产品;
V(mutex);
V(empty);
}
}
问题:能否改变相邻P、V操作的顺序?
不能改变P操作的顺序,因为当empty = 0,full = n时会发生死锁的现象。
可以改变V操作的顺序。