思维总览

知识总览

在这里插入图片描述

信号量机制实现进程互斥

信号量的数据结构

1
2
3
4
typedef struct {
int value;
struct process *L;
}semaphore;

信号量机制实现进程同步

**进程同步:**让各个并发的进程按要求有序的进行

**进程同步问题:**让本来异步并发的进程互相配合,有序推进

在这里插入图片描述

核心:前V后P

信号量机制和前驱关系

在这里插入图片描述

需要认识到,每一对前驱关系都是一个进程同步问题

生产者消费者问题

  • 系统中有一组生产者进程一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。(注: 这里的”产品”理解为某种数据)
  • 生产者、消费者共享一个初始为空、大小为n的缓冲区
  • 只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。
  • 只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。
  • 缓冲区是临界资源,各进程必须互斥地访问。

缓冲区是临界资源,各个进程必须互斥的访问:防止两个生产者想同一块缓冲区放入资源或者防止两个消费者同时消费同一块缓冲区的资源

在这里插入图片描述

image-20230511170415418

如何实现

1
2
3
semaphore mutex=1 ; //互斥信号量;
semaphore empty =n; // 同步信号量,表示空闲缓冲区的数量
semaphore full =0; // 同步信号量,表示产品的数量,即非空缓冲区的数量

生产者

1
2
3
4
5
6
7
8
9
10
11
producer(){
while(1){
//生产一个产品
P(empty);
P(mutex);
// 把产品放入缓冲区
V(mutex);
V(full);

}
}

消费者

1
2
3
4
5
6
7
8
9
10
11
consumer(){
while(1){
//消耗一个产品
P(full);
P(mutex);
//从缓冲区取出一个产品
V(mutex);
V(empty);
//使用产品
}
}

上面两端代码有如下的特点:

  1. full 和 empty 的 P, V 操作是在两个不同的进程中实现的,生产者 P(empty)

    V(full) 消费者则相反

  2. 对进程互斥的访问的代码是在同一个进程中实现的

思考:能否改变相邻P,V 操作的顺序? 就是先进行互斥信号量的操作,再进行同步信号量的操作

改变顺序后的代码如下

在这里插入图片描述

因此,实现互斥的P操作一定要在实现同步的P操作之后

V操作不会导致进程阻塞,因此两个V操作可以交换

多生产多消费者问题

问题描述

在这里插入图片描述

多:多类的消费者和生产者

问题分析

在这里插入图片描述

如何实现

有mutex的情况在这里插入图片描述

无mutex的情况

在这里插入图片描述

为什么可以无mutex

原因在于:本题中的缓冲区大小为1,在任何时刻,apple、 orange、 plate 三个同步信号量中最多只有一个是1。因此在任何时刻,最多只有一个进程的P操作不会被阻塞,并顺利地进入临界区

总结:

在生产者_消费者问题中,如果缓冲区大小为1,那么有可能不需要设置互斥信号量就可以实现互斥访问缓冲区的功能。当然,这不是绝对的,要具体问题具体分析。(建议加上mutex肯定不会错)

image-20230511174838441