monitor

1.      The concept of monitoring

1.      A monitor can be regarded as a software module. It encapsulates shared variables and operations on these shared variables to form a functional module with a certain interface. A process can call a monitor to achieve process-level concurrency control.

2.      Processes can only use the monitor process exclusively , that is, when one process uses the monitor process, the other process must wait. When a process is done using the monitor, it must release the monitor and wake up one of the processes waiting for the monitor.

3.      The waiting queue at the entrance of the monitor is called the entry waiting queue . Since the process will perform the wake-up operation, there may be multiple queues waiting to use the monitor. Such a queue is called an emergency queue, and its priority is higher than waiting. queue .

Second,      the characteristics of the tube process

1.      Modular.

A monitor is a basic software module that can be compiled separately.

2.      Abstract data types.

The monitor encapsulates the data and operations on the data, which is a bit like a class in an object-oriented programming language.

3.      Information hiding.

Processes or other software modules outside the monitor can only access the operations provided by the monitor through the external interface of the monitor, and the implementation details inside the monitor are transparent to the outside world.

4.      Mutual exclusivity used .

At any one time, the monitor can only be used by one process. The mutual exclusion when entering the monitor is done by the compiler.

Three,     enter process, leave process, conditional variable c , wait(c)  , signal(c)

1. enter process

An application must be made before a process enters the monitor process, and the monitor process generally provides an external process -- the enter process. For example , Monitor.enter() means that the process calls the monitor external process enter to enter the monitor .

2. Leave process

When a process leaves the monitor, if the emergency queue is not empty, it must be responsible for waking up a process in the emergency queue. At this time, the monitor also provides an external process -leave process, such as Monitor.leave(), which means that the process calls The external process of the monitor monitor leaves the monitor.

3.      Conditional variable c

条件型变量c实际上是一个指针,它指向一个等待该条件的PCB队列。如notfull表示缓冲区不满,如果缓冲区已满,那么将要在缓冲区写入数据的进程就要等待notfull,即wait(notfull)。相应的,如果一个进程在缓冲区读数据,当它读完一个数据后,要执行signal(notempty),表示已经释放了一个缓冲区单元。

4.     wait(c)

wait(c)表示为进入管程的进程分配某种类型的资源,如果此时这种资源可用,那么进程使用,否则进程被阻塞,进入紧急队列。

5.     signal(c)

signal(c)表示进入管程的进程使用的某种资源要释放,此时进程会唤醒由于等待这种资源而进入紧急队列中的第一个进程。

四、     应用实例

案例一:生产者消费者问题。生产者进程将产品放入某一缓冲区,消费者进程到此缓冲区中取产品。这个过程必须保证:1. 当缓冲区有剩余空间时,生产者才能在其中放入产品;2. 当缓冲区有数据时,消费者才能在其中取出产品。

解决方案:使用管程机制来实现生产者和消费者之间的同步互斥问题

1.     假设有一基本管程monitor,提供了enter、leave、signal、wait等操作;

2.     条件变量notfull表示缓冲区不满,条件变量notempty表示缓冲区不空;

3.     缓冲区buff[0...n-1]用来存放产品,最大可放n件产品;

4.     定义整型变量count表示缓冲区当前的产品数,指针in指向缓冲区当前第一个空的位置,指针out指向缓冲区当前第一个不空的位置;

5.     定义过程add(ItemType item)

add(ItemTypeitem) //生产者进程在缓冲区放入产品

{

   if(count==n) wait(notfull);

 //如果此时缓冲区已满,那么进程必须等待notfull,这意味着进程已经被阻塞到紧急队列里

   buff[in]=item; //否则在第一个空的位置放入产品

   in=(in+1)%n; //指针循环加1

count++;

   signal(notempty);

//此时缓冲区已经多了一个产品,也就是说生产者进程去唤醒因取不到产品被阻塞的消费者进程

}

6.     定义过程ItemType remove()

ItemType remove()    //消费者进程在缓冲区取出产品

{

      if(count==0) wait(notempty);

//如果缓冲区没有产品,那么消费者必须等待notempty,也就是被阻塞到紧急队列中去

      item=buff[out]; //消费者从第一个不空的位置取出产品

      out=(out+1)%n;

      signal(notfull);

//此时缓冲区多了一个空的单元,也就是消费者进程去唤醒因缓冲区已满而不能放入产品的生产者进程

      return item;

}

7.     生产者进程代码段

while(true)

{

      produce(&item); //生成出一件产品

      monitor. enter(); //进入管程

      monitor. add();  //调用add方法,放入产品

      monitor. leave(); //离开管程

}

8.     消费者进程代码段

while(true)

{

      monitor. enter();

      item=monitor. remove(); //取出产品

      monitor. leave();

consumer(&item); //进行消费

}

案例二:读者写者问题。现有一个缓冲区,有若干读者进程和若干写者进程。读者进程在缓冲区读数据,写者进程在缓冲区写入数据。这个过程必须保证:1. 读者进程之间不需要互斥;2.写者进程之间必须互斥,即当一个写者进程在缓冲区写入数据时,别的写者进程必须被阻塞;3. 读者进程和写者进程必须互斥,即当有读者进程在读数据,写者进程必须被阻塞,有写者进程在写数据时,读者进程必须被阻塞。

解决方案:采用管程机制来解决读者写者问题

1. 假设已经有一个基本管程Monitor提供了enter、leave、signal、wait等操作;

2. 定义条件变量r表示可以对缓冲区读,条件变量w表示可以对缓冲区写;

3. 定义布尔类型变量IsWriting表示当前有写者进程在缓冲区写数据;

4. 整型变量read_count表示读数据的个数;

5. 定义过程startRead()

void startRead()

{

      if(IsWriting) wait(r);

   //此时缓冲区有写者进程在写数据,那么读者进程等待r,也就是读者进程被阻塞到紧急队列中

      read_count++; //否则,读出数据

      signal(r); //唤醒被阻塞的读者进程

}

6.     定义过程endRead()

void endRead()

{

      read_count--;

if(read_count= =0) signal(w);

   // 此时表示所有读者进程都已经读完数据,那么唤醒被阻塞的写                 者进程

}

7.     定义过程startWrite

void startWrite()

{

      if(read_count!=0 || IsWriting) wait(w);

   //此时表示如果有读者进程存在或者其他写者进程存在,那么将要写数据的写者进程被阻塞

      IsWriting=true;

}

8.     定义过程endWrite()

void endWrite()

{

      IsWriting=false;

      if(r!=null) signal(r);

   //如果有读者进程存在,那么唤醒读者进程

      else signal(w); //否则唤醒写者进程

}

9.     读者进程代码段

while(true)

{

      Monitor. enter();

      Monitor. startRead();

      read();

      Monitor. endRead();

      Monitor. leave();

}

10.  写者进程代码段

while(true)

{

      Monitor. enter();

      Monitor. startWrite();

      write();

      Monitor. endWrite();

      Monitor. leave();

}

注:需要互斥的操作放在管程之间

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326076407&siteId=291194637