生产者消费问题
1.1 生产者消费者问题分析
生产者和消费者共享一个缓冲区;生产者生产"数据"到缓冲区,消费者从缓冲区中拿走"数据",此外根据问题得出缓冲区没有"数据"的时候,消费者不能取"数据",同理,缓冲器"数据"满的时候,生产者就不能生产"数据",此外缓冲区还是一个互斥资源,生产者和消费者不能同时访问。
由此问题分析完毕总结如下:
- 缓冲区是互斥资源,生产者和消费者要互斥访问。
- 缓冲器满则不能生产;缓冲区空则不能取。
根据两个条件,设置三个信号量;
mutex = 1; // 互斥信号量
empty = n; // 空信号量
full = 0; // 满信号量
2.1 生产者消费者问题伪代码实现
semaphore mutex=1; //临界区互斥信号量
semaphore empty=n; //空闲缓冲区
semaphore full=0; //缓冲区初始化为空
producer ()//生产者进程
{
while(1)
{
produce an item in nextp; //生产数据
P(empty); //获取空缓冲区单元
P(mutex); //进入临界区.
add nextp to buffer; //将数据放入缓冲区
V(mutex); //离开临界区,释放互斥信号量
V(full); //满缓冲区数加1
}
}
consumer ()//消费者进程
{
while(1)
{
P(full); //获取满缓冲区单元
P(mutex); // 进入临界区
remove an item from buffer; //从缓冲区中取出数据
V (mutex); //离开临界区,释放互斥信号量
V (empty) ; //空缓冲区数加1
consume the item; //消费数据
}
}
3.1 注意事项(由于p操作次序不当造成的自锁)
- 若生产者进程已经将缓冲区放满,消费者进程并没有取产品,即 empty = 0,当下次仍然是生产者进程运行时,它先执行 P(mutex)封锁信号量,再执行 P(empty)时将被阻塞,希望消费者取出产品后将其唤醒。轮到消费者进程运行时,它先执行 P(mutex),然而由于生产者进程已经封锁 mutex 信号量,消费者进程也会被阻塞,这样一来生产者进程与消费者进程都将阻塞,都指望对方唤醒自己,陷入了无休止的等待。
- 若消费者进程已经将缓冲区取空,即 full = 0,下次如果还是消费者先运行,也会出现类似的死锁。
不过生产者释放信号量时,mutex、full 先释放哪一个无所谓,消费者先释放 mutex 还是 empty 都可以。
/**
*@anthor 2021/4/16 22:47:28 cn.edu.zzuli
*/