我可以使用任何一种原语来使其工作,但我想从性能的角度来看,哪种原语更适合这种情况。
我只需要同步两个进程。总是有两个,不多也不少。一个写入内存映射文件,而另一个以生产者/消费者方式读取。我关心性能,考虑到场景有多简单,我想我可以使用一些轻量级的东西,但我不确定哪个更快,但对于这种场景仍然足够。
我可以使用任何一种原语来使其工作,但我想从性能的角度来看,哪种原语更适合这种情况。
我只需要同步两个进程。总是有两个,不多也不少。一个写入内存映射文件,而另一个以生产者/消费者方式读取。我关心性能,考虑到场景有多简单,我想我可以使用一些轻量级的东西,但我不确定哪个更快,但对于这种场景仍然足够。
第一点:它们都是内核对象,所以它们都涉及从用户模式到内核模式的切换。这本身就产生了足够的开销,以至于您不太可能注意到它们之间在速度或类似方面的任何真正差异。因此,哪个更可取将在很大程度上取决于您如何在共享内存区域中构建数据,以及您如何使用它。
让我们从可能是最简单的情况开始:共享内存区域形成了瓶颈。消费者不阅读的所有时间,生产者都在写,反之亦然。至少在最初,这似乎是我们可以使用单个互斥锁的情况。生产者等待互斥体,写入数据,释放互斥体。消费者等待互斥体,读取数据,释放互斥体。这种情况一直持续到一切完成。
不幸的是,虽然这可以防止生产者和消费者同时使用共享区域,但它并不能确保正确操作。例如:生产者写入一个充满信息的缓冲区,然后释放互斥体。然后它再次等待互斥锁,所以当读取器完成后,它可以写入更多数据——但在这一点上,不能保证消费者将是下一个获得互斥锁的人。生产者可能会立即将其取回,并在其刚刚生成的内容上写入更多数据,因此消费者将永远不会看到以前的数据。
防止这种情况的一种方法是使用几个事件:一个从生产者到消费者说有数据等待读取,另一个从消费者到生产者说缓冲区中的所有数据都已被读取读。在这种情况下,生产者等待其事件,消费者只有在完成读取数据时才会设置该事件。生产者然后写入一些数据,并通知消费者的事件说一些数据已准备好。消费者读取数据,然后向生产者发送事件信号,以便循环继续。
只要您只有一个生产者和一个消费者,并将整个数据视为一起控制的单个“块”数据,这就足够了。但是,这可能会导致问题。例如,让我们考虑一个 Web 服务器前端作为生产者,后端作为消费者(以及一些将结果传递回 Web 服务器的单独机制)。如果缓冲区小到只能容纳一个请求,则生产者可能必须在消费者处理一个请求时缓冲几个传入的请求。每次消费者准备好处理请求时,生产者必须停止它正在做的事情,将请求复制到缓冲区,并让消费者知道它可以继续。
The basic point of separate processes, however, is to let each proceed on its own schedule as much as possible. To allow that, we might make room in our shared buffer for a number of requests. At any given time, some number of those slots will full (or, looking at it from the other direction, some number will be free). For this case, we just about need a counted semaphore to track those slots. The producer can write something any time at least one slot is free. The consumer can read something anytime at least one slot is filled.
Bottom line: the choice isn't about speed. It's about how your use/structure the data and the processes' access to it. Assuming it's really as simple as you describe, the pair of events is probably the simplest mechanism that will work.