管程的作用

让写代码的不用再去考虑互斥问题(互斥问题由编译器自行解决),可以更好地投入到其他的逻辑思考当中

管程的代码实现

管程的代码实现有点面向对象的意思,下面以生产者(Producer)消费者(Consumer)问题展开

生产者和消费者问题中有以下数据

  • count 当前在缓冲区中的资源的数量
  • MAX_NUMBER 缓冲区的最大容量

其中的count是一个共享数据会被多个进程争夺使用权,但我们使用了管程技术所以现在不需要担心多个进程对该变量的争抢问题

除了数据以外我们还需要定义对数据的操作(行为),在生产者消费者问题中我们会有以下操作

  • insert 表示生产者将一个产品放入缓冲区
  • remove 表示消费者将一个产品从缓冲区中取出

管程虽然帮助我们解决了互斥的问题,但同步的问题依旧需要我们自己写代码解决

管程为我们提供了两个方法用于解决同步问题

  • wait() 调用该方法后进程进入阻塞队列
  • signal() 调用该方法后会从阻塞队列中弹出一个进程执行

在编写insert方法以及remove方法时我们需要注意以下几点

  1. 比如在执行insert方法的count++ 语句之前我们应该检查当前缓冲区是否已经满了,如果满了那么当前的进程应该执行wait()方法进行等待而不是继续往缓冲区里面写入数据
  2. 并且如果我们将count++ 语句执行完成后,发现count变量的值为1,那么我们就应该执行signal()方法,告诉系统现在可以让因资源不足而阻塞的remove进程上处理机运行

同理在编写remove方法时我们也需要做到以下几点

  1. 在执行remove方法的count-- 语句之前我们应该检查当前缓冲区中是否有资源可以取出,如果没有资源可以取出那么当前进程应该执行wait()方法进行等待而不是从缓冲区中取出数据
  2. 并且如果我们将count-- 语句执行完成后,发现count变量的值小于MAX_NUMBER,那么我们就应该执行signal()方法,告诉系统现在可以让因缓冲区满而祖肃的insert方法上处理机运行

下面是具体的实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
monitor ProducerAndConsumer

int count = 10;
int MAX_NUMBER = 5;

void insert(Product product){
// 如果当前缓冲区的资源数量已经到了缓冲区资源数量的极限值那么进程应该进行等待
if (count == MAX_NUMBER) {
wait();
}
count++;
// 如果在进行增加后的缓冲区的资源数量到达了最低可以取出的数量1 那么系统应该唤醒等待队列中的remove进程
if (count == 1) {
signal();
}
}

Product remove() {
// 如果当前缓冲区中没有资源 即资源数量为0 那么进行应该进行等待
if (count == 0) {
wait();
}
count--;
// 如果在资源被取出后缓冲区的资源数量到了最低可增加的数量 MAX_NUMBER-1 那么系统应该唤醒等待队列中的insert 进程
if (count == MAX_NUMBER-1) {
signal();
}

}


end monitor