先决条件–
操作系统中的信号灯
,
进程间通讯
生产者消费者问题是经典的同步问题。我们可以通过使用信号量来解决这个问题。
一种
信号
S是一个整数变量, 只能通过两个标准操作来访问:wait()和signal()。
wait()操作将信号量的值减少1, 而signal()操作将其值的值增加1。
wait(S){
while(S<=0); // busy waiting
S--;
}
signal(S){
S++;
}
信号量有两种类型:
- 二进制信号量–这类似于互斥锁, 但不相同。它只能有两个值– 0和1。它的值初始化为1。它用于通过多个过程来解决临界区问题。
- 计数信号量–其值的范围可以是不受限制的域。它用于控制对具有多个实例的资源的访问。
问题陈述 -我们有一个固定大小的缓冲区。生产者可以生产物品, 也可以放置在缓冲区中。消费者可以挑选物品并可以消费它们。我们需要确保当生产者将一个项目放置在缓冲区中时, 消费者同时不应消耗任何项目。在此问题中, 缓冲区是关键部分。
为了解决这个问题, 我们需要两个计数信号量– Full和Empty。在任何给定时间, "满"将跟踪缓冲区中的项目数, 而"空"将跟踪未占用的插槽数。
信号量的初始化–
互斥锁= 1
Full = 0 //最初, 所有插槽均为空。因此, 完整插槽为0
空= n //所有插槽最初都是空的
生产者解决方案–
do{
//produce an item
wait(empty);
wait(mutex);
//place in buffer
signal(mutex);
signal(full);
}while(true)
当生产者生产一个项目时, "空"的值将减少1, 因为现在将填充一个插槽。互斥锁的值也减小了, 以防止使用者访问缓冲区。现在, 生产者已经放置了该项目, 因此" full"的值增加了1。由于生产者的任务已经完成并且消费者可以访问缓冲区, 因此互斥量的值也增加了1。
消费者解决方案–
do{
wait(full);
wait(mutex);
// remove item from buffer
signal(mutex);
signal(empty);
// consumes item
}while(true)
当消费者从缓冲区中删除项目时, " full"的值将减少1, 并且互斥量的值也将减少, 以使生产者此时无法访问缓冲区。现在, 消费者已经消费了该商品, 因此将"空"的值增加了1。互斥量的值也增加了, 以便生产者现在可以访问缓冲区。
参见实施–Java中使用信号量的生产者-消费者解决方案|套装2