生产者-消费者问题

问题描述
生产者-消费者问题_第1张图片
生产者-消费者
问题分析
  • 任何时刻只能有一个线程操作缓冲区(互斥访问)
  • 缓冲区为空时,消费者必须等待生产者(条件同步)
  • 缓冲区为满时,生产者必须等待消费者(条件同步)
用信号量描述每个约束
  • 二进制信号量mutex
  • 资源信号量fullBuffers
  • 资源信号量emptyBuffers
具体实现:
class BoundedBuffer{
    mutex = new Semaphore(1);
    fullBuffers = new Semaphore(0);
    emptyBuffers = new Semaphore(n);
}

BoundedBuffer::Deposit(c){
    //缓冲区空间减一
    emptyBuffers->P();
    //进入互斥访问
    mutex->P();
    Add c to the buffer;
    mutex->V();
    //离开临界区
    //生产资源加一
    fullBuffers->V();
}

BoundedBuffer::Remove(c){
    //生产资源减一
    fullBuffers->P();
    mutex->P();
    Remove c from buffer;
    mutex->V();
    //缓冲区空间加一
    emptyBuffers->V();
}
使用信号量的困难
  • 读/开发代码比较困难:程序员需要能运用信号量机制
  • 容易出错
    a. 使用的信号量已经被另一个线程占用
    b. 忘记释放信号量
使用管程实现:
class BoundedBuffer{
    Lock lock;
    int count = 0; //表示当前buffer的资源
    Condition notFull,notEmpty; //两个条件变量
}

BoundedBuffer::Deposit(c){
    lock->Acquire();
    //若缓存区满时,则放弃管程访问
    while(count == n){
        notFull.Wait(&lock);
    }
    Add c to the buffer;
    count ++;
    //唤醒等待的消费者
    notEmpty.Signal();
    lock->Release();
}

BoundedBuffer::Remove(c){
    lock->Acquire();
    //若生产资源为空时,放弃管程访问
    while(count == 0){
        notEmpty.Wait(&lock);
    }
    Remove c from buffer;
    count --;
    //唤醒等待的生产者
    notFull.Signal();
    lock->Release();
}

管程操作可以将PV操作放在一个模块中,可以简化PV操作。

你可能感兴趣的:(生产者-消费者问题)