操作系统:用信号量实现进程互斥和同步

730 阅读2分钟

一.信号量机制实现进程互斥

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操作的顺序。