Monitors

2017-03-28  本文已影响0人  Fruit_初

monitor Condition variable


管程


管程的定义
管程是对共享数据的访问进行控制的特殊的一段程序:

管程是一个压缩了如下内容的模块:

它能够:


管程的语义

我的理解:管程包括了对共享数据的处理函数。用户只能使用管程提供的方式,不能自定义;但在临界区中用户可以对共享数据做任何事情。临界区是指会对共享数据产生data race的代码段,无论是否采取保护措施临界区都是存在的。而管程可以被认为是对临界区进行保护的一段代码,包装了临界区和对其互斥访问的管理。


管程的使用实例

Monitor account {
  double balance;
  double withdraw(amount) {
  balance = balance –amount;
  return balance;
  }
}
例子

如果一个线程想在管程中等待呢?——条件变量(condition variables)

Attention:

共享变量并不是if语句中的判断条件,所以不能if(condition) { ... }

条件变量是:

条件变量 & 锁

条件变量不能代替锁,而是和锁互补的一种机制

首先释放锁,将线程放到condition的等待队列中,如果线程再醒过来,将重新获得锁。
在放在等待队列的时候,会让线程sleep,等sleep返回的时候,它是被另外一个持有锁的线程叫醒的。

叫醒一个在condition的等待队列上的线程

叫醒所有在 condition的等待队列上的线程

条件变量 & 管程:

管程中的一个条件变量一般表示的含义是:一个线程要在管程中继续运行所需要的条件(比如消费者需要资源不为空才能消费)

Monitor M {
    ...monitored variables;
    Condition c, d;
    
    void enter_monitor(...) {
        if( extra property C not true) wait(c); //等待管程的锁
        do what you have to do 
        if(extra property true D) signal(d);//叫起在d上等待的线程
    }
}

一般条件变量对应的操作为:
Wait( ) : 等待管程的锁,或者等待条件变量被signal了
`Signal( ):’ 叫醒一个等待线程
'Broadcase( ):' 叫醒所有等待线程


条件变量 != 信号量
有条件变量的管程 != 信号量

但它们可以相互实现

其区别在于,对管程访问用锁控制,下面是具体分析:



使用管程和条件变量解决实际问题


(一)有限缓冲区问题描述:
有一个被producer和consumer共享的资源池

producer和consumer执行速度不同:

安全要求:

有限缓冲区代码

Monitor bounded_buffer {
    Resource buffer[N];
    //Variables for indexing buffer
    Condition not_full;  //space in buffer;
    Condition not_empty; //value in buffer
    
    void put_resource (Resource R){
        if(buffer array is full) 
            wait(not_full);
        Add R to buffer array;
        signal(not_empty);
    }
    Resource get_resource() {
        if(buffer array is empty)
            wait(not_empty);
        Get resource R from buffer array;
        signal(not_full);
        return R;
    }
}

(二)读者写者问题

分析:

实现:

Monitor RW {
    int nr = 0, nw = 0;
    Condition canRead, canWrite;
    
    void StartRead() {
        while(nw != 0) wait(canRead);
        nr++;
    }
    void EndRead() {
        nr--;
        if(nr == 0) signal(canWrite);
    }
    void Start Write() {
        while(nr != 0 || nw != 0) wait(canRead);
        nw++;
    }
    void EndWrite() {
        nw--;
        signal(canWrite);
        signal(canRead);
    }
}

两种不同的管程实例——Hoare管程和Mesa管程


两者的区别主要是signal()的语义不一样

Hoare monitors(original)

Mesa monitors(Mesa,Java)


具体使用的区别:
Hoare:

if(empty)
    wait(condition)

Mesa:

while(empty)
    wait(condition)

比较:
Mesa管程更易于使用,也更有效

Hoare管程则相对不够灵活

上一篇下一篇

猜你喜欢

热点阅读