Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 生产者消费者仅使用1个附加信号量_Multithreading_Operating System_Mutex_Semaphore - Fatal编程技术网

Multithreading 生产者消费者仅使用1个附加信号量

Multithreading 生产者消费者仅使用1个附加信号量,multithreading,operating-system,mutex,semaphore,Multithreading,Operating System,Mutex,Semaphore,在操作系统中,正如您在上面针对生产者-消费者的链接中所看到的,使用了两个信号量full和empty,为什么不能仅使用一个数量信号量fullEmpty 我的意思是,我们有一个二进制信号量mutex和另一个信号量fullEmpty,它最初是0,因为缓冲区中没有项目,所以为什么我们需要2个信号量(full,empty) 唯一需要更改的是wait和signal的顺序,以便fullEmpty的更新在关键部分内 有什么想法或原因吗?描述中与您的答案相关的关键陈述是“我们有一个固定大小的缓冲区。” 为了回答您

在操作系统中,正如您在上面针对生产者-消费者的链接中所看到的,使用了两个信号量
full
empty
,为什么不能仅使用一个数量信号量
fullEmpty

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

唯一需要更改的是
wait
signal
的顺序,以便
fullEmpty
的更新在关键部分内


有什么想法或原因吗?

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

为了回答您的问题,我们首先假设缓冲区可以扩展以适应所需的任意多个项目,或者换句话说,缓冲区可以增长到无限大。在这种情况下,生产者和消费者之间需要进行的唯一同步(除了锁定互斥锁以确保不会损坏关键部分中的项目外)将是确保消费者仅在生产者生产项目之后才消费这些项目。只需一个互斥和一个信号量就可以解决这个问题。以下是我从您共享的链接中借用并更改的一些代码:

制作人

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);
消费者

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);
正如您在上面所看到的,生产者总是能够向队列中添加内容(除了持有互斥锁时),并且不需要等待消费者消费任何内容,因为缓冲区永远不会填满,即使消费者不消费项目。另一方面,在生产者生产商品之前,消费者不能消费任何东西


要回答您的问题,您需要关注“我们有一个固定大小的缓冲区”这句话。这改变了问题。由于缓冲区无法再增长到无限大小,您需要让生产者等待缓冲区已满,然后才能向缓冲区添加更多内容。这就是为什么需要第二个信号量。不仅消费者需要等待生产者,现在生产者也需要等待消费者。通过让生产者调用只有消费者调用的信号量
signal
来让生产者等待消费者


您不能只使用一个信号量,因为生产者必须等待的条件与消费者必须等待的条件不同。因为它们应该能够在不同的条件下减少和超过信号量,所以不能对两者使用相同的信号量。

这是因为您必须等待两个条件:队列为空和队列为满。但经典信号量只允许您等待一个条件—等待信号量不是0

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

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

  • 您可以使用互斥和条件变量构建一个
  • 已经有了这个功能
  • 您可以在Linux上使用(请参阅
    FUTEX_WAIT
    FUTEX_WAKE
    )或在其他操作系统上使用同等软件:在FreeBSD上使用(请参阅
    UMTX_OP_WAIT
    UMTX_OP_WAKE
    ),在Windows 8和更高版本上使用,/
我建议您熟悉
futex
接口-使用它,您可以构建比常规同步对象更强大、更高效的同步对象。今天,大多数OSES提供了一个等价的接口,甚至C++也可能在将来引入类似的内容(参见)。
几点注意:


Linux有一个可以在使用
EFD\u信号量
标志创建时充当信号量的函数,但它的最大值为
0xfffffffffffe
,并且不能更改。也许有一天这个系统调用也会被扩展以支持最大值。

请提供伪代码,这样我们就可以告诉您为什么它不起作用了。一个无界的P-C队列只有一个信号量和一个互斥量就可以了,但是一个有界的队列tht可以正确地与多个生产者/消费者一起工作,需要两个信号量和互斥量。谢谢你的回答。我的逻辑是,如果我们有一个计数信号量,它已经作为一个参数给定了一个固定的
n
,即使对于具有“大小有界的缓冲区”的版本,为什么我们不能像第一个示例中那样只使用一个信号量
full
?我的意思是说,如果
full
是定义的最大容量,那么使用这个计数信号量,我们可以保证不能
signal(full)
。我想我们可以在这个Java中像
Semaphore full=new Semaphore(n,true)
?@BrijendarBakchodia感谢您的澄清。你的一个假设是无效的。信号量没有最大计数:您可以根据需要多次调用信号量上的
signal()
:调用将始终成功,而不会阻塞(当然,我在这里忽略整数溢出,但您的问题不必担心这一点)
n
只是您分配给信号量的初始计数,而不是最大计数。@BrijendarBakchodia因此,由于您无法阻止
signal()
,因此必须使用两个不同的信号量。如果您可以为一个信号量设置一个最大计数,然后在达到该计数后阻塞
signal()
,那么您可以只使用一个信号量。@BrijendarBakchodia当然,可以实现一个具有最大计数的信号量。这个决定取决于设计师。我在课堂上使用和学习的传统信号量没有最大值