Concurrency 消费者-生产者算法的混合求解

Concurrency 消费者-生产者算法的混合求解,concurrency,producer-consumer,mutual-exclusion,Concurrency,Producer Consumer,Mutual Exclusion,我试图证明生产者/消费者问题的以下解决方案不起作用,通过表明当消费者在M1开始时,有一种情况是它无法在有限的时间内将某个项目出列,和/或有一种情况是生产者在L2开始时,而且它将无法在有限的时间内将项目排队。我只是找不到任何例子来证明这一点 该算法假设有10个生产者、10个消费者和10个缓冲区大小 nf = 0; // counting semaphore, # of items in queue bm = 1; // binary semaphore, ensures mutex 制作人 L1

我试图证明生产者/消费者问题的以下解决方案不起作用,通过表明当消费者在M1开始时,有一种情况是它无法在有限的时间内将某个项目出列,和/或有一种情况是生产者在L2开始时,而且它将无法在有限的时间内将项目排队。我只是找不到任何例子来证明这一点

该算法假设有10个生产者、10个消费者和10个缓冲区大小

nf = 0; // counting semaphore, # of items in queue
bm = 1; // binary semaphore, ensures mutex
制作人

L1: Produce(item);
L2: P(bm);
If (queue_is_full) {
  V(bm);
  GoTo L2;
} else {
  Enqueue(item);
  V(bm);
  V(nf);
  GoTo L1;
}
消费者

M1: P(nf);
P(bm);
Dequeue(item);
V(bm);
Consume(item);
GoTo M1;

如果我的理解是正确的,p(x)将锁定到x!=0和v(x)总是做x++

在上述代码中
M1:p(nf)
仅在队列中有可用项目时才允许消费者通过。然后它总是获取并释放bm上的锁。因此,我非常确定代码不会与其他消费者或生产者陷入僵局

在生产商中,它获得bm,然后在列表上进行操作。它在v(bm)之前不获取任何其他锁,并且在两个分支中执行v(bm),因此它保证会发生。因为v(bm)最终会发生,所以消费者最终可以消费一件物品。在v(bm)之后,v(nf)是有保证的,因此当一个产品被生产出来时,一个消费者将试图最终消费它

因此,除非出现listcapacity==0这样的愚蠢情况,否则代码看起来很好


如果使用者执行了p(bm)->p(nf)->V(bm),则会出现问题,但上面的代码看起来很好

这是否可能与活动锁有关?对我认为所有的并发问题都是错误的。但信号量应该可以防止这种情况发生。并发错误通常更多地与死锁有关。。活锁在本质上通常是假设的,除非信号量被设计为优先考虑某类客户。例如,在上面的代码中,没有任何东西可以阻止代码在生产者中持续循环,总是在其他人获得锁之前获得锁。(尽管在现实生活中,由于并发系统的不确定性,您可能会期望其他人获得锁,尽管无法保证实现这一点所需的时间有限。如果您希望您参考生产商获取锁的活锁,检查队列是否已满,请重新租赁锁,然后拿走,消费者在错误的时间检查锁,等等?如果不是,我会很感激一个例子。谢谢。谢谢你的广泛解释。这很有意义,我得出了相同的结论。我今天应该了解更多,然后让你知道。代码实际上不起作用。制作人可以保留填充队列,消费者清空队列,而另一个制作人检查队列是否在错误的时间满了,并永远循环。@bluepanda这将是一个活锁。假设有一个producerA和一个producerB。因此a生产并存储一个项目。队列现在满了。制作人B尝试存放其项目,但由于队列已满,因此无法存放完全。消费者C来消费物品。现在A或B或系统中的任何其他生产者都可以存放他们的物品,哪个生产者可以做p(bm)应该是非确定性的。上面的答案说代码中没有死锁,因为我在原始注释中提到了活锁。如果有死锁,我真的希望看到执行的痕迹。