OS学习笔记——管程

管程由过程、变量及数据结构组成,它们共同构建了一个特殊的模块或软件包。进程可以在任意时刻调用管程中的进程,但不允许使用管程外的过程访问管程内的数据结构。

管程在任一时刻都只能有一个活跃进程。这一特性可以帮助管程有效地实现互斥。管程作为一种特殊的程序被编译器识别,每当进程调用管程时,编译器都会采用与其他过程调用不同的方法来处理。这种方法的独特之处在于,当一个进程调用管程中的过程时,该过程中的前几条指令将检查管程中是否有其他活跃进程。如果有,则新到的调用进程就会被阻塞,等待当前在管程中的活跃进程退出管程时将其唤醒。如果无,则新到进程进入管程。


在管程中,除了实现互斥以外,还要保证能将无法继续运行的进程正确阻塞。

引入条件变量以及一对wait、signal操作。其含义为:

1.

x.wait表示正在调用管程的进程因x条件需要被阻塞或者挂起,该进程在执行wait操作时将自己插入x条件的等待队列中,并释放管程。此时其他进程可以使用管程完成自身工作。当x条件发生变化时,系统调度程序将选择等待队列中的一个进程继续执行;


2.

x.signal表示正在调用管程的进程发现x条件发生了变化,则使用signal操作唤醒一个因x条件被阻塞或挂起的进程。


在不同的操作系统中,当对某条件变量执行signal操作以后,能够进入管程运行的调用进程可以由不同选择。设进程A在运行过程中条件变量x发生了变化,而该条件变量x上有调用进程B在等待,此时可以选择以下三种不同的设计方法:

1. 进程A时刻监控条件变量x的变化,当发现x变化时仍然继续执行,直到自身退出才唤醒B进程进入管程运行。

2.进程A时刻监控条件变量x的变化,当发现x变化时立即让出管程,让进程B进入管程,同时阻塞自身。

3.将对条件变量x的变化检查放在进程A退出管程时进行,P操作只能作为一个管程过程的最后一条语句出现,此时进程A无须花费额外时间监控条件变量x的变化也能保证进程B随条件变量x的变化而被唤醒。

使用管程解决生产者消费者问题

monitor ProducerConsumer
condition full,empty;
int count;

void insert(int item)
{
 if(count == N)
  wait(full);
 insert(item);
 count = count +1 ;
 if(count == 1)
  signal(empty);
}

int remover()
{
 if(count == 0)
  wait(empty);
 remove = remove_item;
 count = count - 1;
 if(count == N-1)
  signal(full);
}

count = 0;
end monitor
void producer()
{
 while(true)
 {
  item = produce_item;
  ProducerConsumer.insert(item);
 }
}

void consumer()
{
 while(true)
 {
  item = ProducerConsumer.remove;
  consume(item);
 }
}



猜你喜欢

转载自blog.csdn.net/Serenity0614/article/details/78780879