操作系统学习笔记——管程,用管程解决生产者消费者问题

抽象程度比信号量更高。

目的:分离互斥和条件同步的关注

什么是管程:

       一个锁:指定临界区;0或者多个条件变量:等待/通知信号量用于管理并发访问共享数据。

一般方法:

       收集在对象/模块中的相关共享数据;定义方法来访问共享数据。

Lock

     Lock::Acquire() - 等待知道锁可用,然后抢占锁

     Lock::Release() - 释放锁,唤醒等待者如果有的话

Condition Variable

     允许等待状态进入临界区:允许处于等待(睡眠)的线程进入临界区;某个时刻原子释放锁进入睡眠

     Wait() operation: 释放锁,睡眠,重新获得锁返回后

     Signal() operation (or broadcast()  operation ):唤醒等待者(或者所有等待者),如果有

条件变量实现:

        需要维护每个条件队列;线程等待的条件等待signal()

class Condition{
    int numWaiting = 0;
    WaitQueue q;
}

Condition::Wait(lock){
    numWaiting++;
    Add this thread t to q;
    release(lock);
    schedule();//need mutex
    require(lock);
}

Condition::Signal(){
    if(numWaiting > 0){
        Remove a thread t from q;
        wakeup(t)://need mutex
        numWaiting--;
    }
}

numWaiting当前等待队列中的个数。注意在scedule之前释放锁的操作。

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

class BoundedBuffer{
    ...
    Lock lock;
    int count = 0;
    Condition notFull,notEmpty;
}

BoundedBuffer::Deposit(c){
    lock->Acquire();
    while(count == n)
        notFull.Wait(&lock);//这个lock就是之前说的事先释放的锁
    Add c to the buffer;
    count++;
    notEmpty.Signal();
    lock->Release();    
}

BoundeBuffer::Remove(c){
    lock->Acquire();
    while(count == 0)    
        notEmpty.Wait(&lock);
    Remove c from buffer;
    count--;
    notFull.Signal();
    lock->Release();
}

只能一个线程进入管程,所以在头尾有 锁 包起来,实现互斥。

猜你喜欢

转载自blog.csdn.net/qq_22080999/article/details/82380243