生产者消费者仅使用1个额外的信号量

问题描述 投票:2回答:2

Solution traditional to producer-consumer

在操作系统中,正如您在上面的生产者消费者链接中看到的那样,使用了两个信号量fullempty,为什么不能仅使用一个数量信号量fullEmpty来执行此操作。

我的意思是,我们有一个二进制信号量mutex和另一个信号量fullEmpty,最初是0,因为缓冲区中没有项目,为什么我们需要2个信号量(fullempty)?

唯一的事情是waitsignal的顺序需要改变,以便fullEmpty的更新在关键部分。

有什么想法或原因吗?

multithreading operating-system mutex semaphore
2个回答
1
投票

描述中与您的答案相关的关键声明是“我们有一个固定大小的缓冲区”。

为了回答你的问题,我们首先假设缓冲区可以根据需要扩展以适应尽可能多的项目,换句话说,缓冲区可以增长到无限大小。在这种情况下,生产者和消费者之间需要进行的唯一同步(除了锁定互斥锁以确保您不会破坏关键部分中的项目)将确保消费者仅在消费者生产后使用物品。制片人。你可以用一个互斥量和一个信号量来解决这个问题。这是一些代码,我从你分享的链接中借用和更改了这些代码:

制片人

do {
    //produce an item

    wait(mutex);

    //place in buffer

    signal(mutex);
    signal(full);

} while (true);

消费者

do {
    wait(full);
    wait(mutex);

    //remove item from buffer

    signal(mutex);

    //consume item

} while (true);

正如您在上面所看到的,生产者始终能够向队列添加内容(除了保持互斥锁时)并且不需要等待消费者消费任何东西,因为缓冲区永远不会填充,即使消费者不要消耗物品。另一方面,在生产者生产物品之前,消费者不能消费任何东西。


要回答你的问题,你需要关注声明,“我们有一个固定大小的缓冲区。”这改变了问题。由于缓冲区不再能够增长到无限大小,因此您需要让生产者在缓冲区已满时等待,然后才能向缓冲区添加更多内容。这就是你需要第二个信号量的原因。消费者不仅需要等待生产者,而且现在生产者需要等待消费者。你让生产者等待消费者,让他们在信号量上调用wait,只有消费者才能打电话给signal

您不能只使用一个信号量执行此操作,因为生产者必须等待的条件与消费者必须等待的条件不同。由于它们应该能够在不同条件下递减并超过信号量,因此不能对两者使用相同的信号量。


0
投票

这是因为您必须等待2个条件:队列为空且队列已满。但是经典信号量允许您只等待一个条件 - 等到信号量不为0。

您可以使用单个同步对象解决此问题,但此类对象需要比信号量更多的功能。 “有界信号量” - 具有最大值的信号量应该足够,因为它允许您阻止等待这两个条件。

如何获得一个是另一个问题:

我建议你熟悉futex界面 - 用它你可以构建比常规界面更强大,更有效的同步对象。今天,大多数操作系统提供了等效的接口,甚至C ++也可能会在未来引入类似的东西(参见std::synchronic<T>)。


几点说明:

Linux有eventfd,它可以在使用EFD_SEMAPHORE标志创建时充当信号量,但它具有最大值0xfffffffffffffffe并且无法更改。也许有一天,这个系统调用将扩展到支持最大值。

© www.soinside.com 2019 - 2024. All rights reserved.