Windows中的两个进程—单个生产者/单个消费者.Mutex、Event或Semaphore哪个更好



我可以使用任何一个原语来使其工作,但我想知道从性能的角度来看,哪一个原语更适合这种场景。

我只需要同步两个进程。总有两个,不多不少。一个写入内存映射文件,另一个以生产者/消费者的方式从中读取。我关心性能,考虑到场景有多简单,我认为我可以使用重量较轻的东西,但我不确定哪一个更快,但仍然适合这种场景。

第一点:它们都是内核对象,所以它们都涉及从用户模式到内核模式的切换。这本身就带来了足够的开销,以至于你不太可能注意到它们之间在速度或诸如此类方面的任何真正差异。因此,哪一个更可取将在很大程度上取决于你如何在共享内存区域中构建数据,以及你如何使用它

让我们从最简单的情况开始:共享内存区域形成了瓶颈。在消费者不阅读的所有时间里,生产者都在写作,反之亦然。至少在最初,这似乎是一个我们可以使用单个互斥体的情况。生产者等待互斥锁,写入数据,释放互斥锁。使用者等待互斥锁,读取数据,释放互斥锁。这种情况一直持续到一切都完成为止。

不幸的是,虽然这可以防止生产者和消费者同时使用共享区域,但它并不能确保正确的操作。例如:生产者写入一个充满信息的缓冲区,然后释放互斥对象。然后,它再次等待互斥锁,这样当读取器完成时,它可以写入更多的数据——但在这一点上,不能保证消费者将是下一个获得互斥锁的人。生产者可能会立即将其取回,并在刚刚生成的上写入更多的数据,这样消费者就永远看不到以前的数据。

防止这种情况的一种方法是使用两个事件:一个从生产者到消费者,表示有数据等待读取,另一个从消费者到生产者,表示缓冲区中的所有数据都已读取。在这种情况下,生产者等待其事件,消费者只有在读取完数据后才会设置该事件。生产者然后写入一些数据,并向消费者的事件发出信号,表示一些数据已准备好。消费者读取数据,然后向生产者发出事件信号,以便循环可以继续。

只要你只有一个生产者和一个消费者将整个数据视为一个单独的"区块",并一起控制,这就足够了。然而,可能会导致问题。例如,让我们考虑将web服务器前端作为生产者,将后端作为消费者(以及将结果传递回web服务器的一些单独机制)。如果缓冲区足够小,只能容纳一个请求,那么生产者可能不得不在消费者处理一个请求时缓冲几个传入请求。每次使用者准备好处理请求时,生产者都必须停止它正在做的事情,将请求复制到缓冲区,并让使用者知道它可以继续。

然而,单独流程的基本点是让每个流程尽可能按照自己的时间表进行。为了实现这一点,我们可能会在共享缓冲区中为一些请求腾出空间。在任何给定的时间,这些插槽中的一些都将被填满(或者,从另一个方向看,一些插槽将是空闲的)。对于这种情况,我们只需要一个计数信号量来跟踪这些插槽。制片人可以在任何时候写一些东西——至少有一个空位是空闲的。消费者可以在至少有一个插槽被填满的任何时候读取内容。

一句话:选择与速度无关。这是关于你如何使用/构建数据以及进程对数据的访问。假设它真的像你描述的那样简单,那么这对事件可能是最简单的机制。

最新更新