消息队列在线程通信中对共享数据的优势是什么?

Jas*_*son 6 c++ windows multithreading message-queue

我读了一篇关于多线程程序设计http://drdobbs.com/architecture-and-design/215900465的文章,它说这是"用异步消息替换共享数据的最佳实践.尽可能地保留每个线程的数据"隔离(非共享),让线程通过传递数据副本的异步消息进行通信".

令我困惑的是,我没有看到使用共享数据和消息队列之间的区别.我现在正在开发一个关于Windows的非gui项目,所以让我们使用windows的消息队列.并以传统的生产者 - 消费者问题为例.

使用共享数据,将有一个共享容器和一个锁定生产者线程和消费者线程之间容器的锁.当生产者输出产品时,它首先等待锁定然后向容器写入内容然后释放锁定.

使用消息队列,生产者可以简单地PostThreadMessage而不用阻塞.这是异步消息的优势.但我认为必须存在一些锁定两个线程之间的消息队列,否则数据肯定会被破坏.PostThreadMessage调用只是隐藏细节.我不知道我的猜测是否正确但是如果它是真的,优势似乎不再存在,因为两种方法都做同样的事情,唯一的区别是系统在使用消息队列时隐藏细节.

PS.也许消息队列使用非阻塞包含器,但我也可以使用前一种方式的并发容器.我想知道消息队列是如何实现的,这两种方式之间是否有任何性能差异?

更新:如果消息队列操作仍然在其他地方被阻止,我仍然没有得到异步消息的概念.如果我猜错了,请纠正我:当我们使用共享容器和锁时,我们将在我们自己的线程中阻塞.但是当使用消息队列时,我自己的线程立即返回,并将阻塞工作留给某个系统线程.

jco*_*der 7

想象一下,你有1个线程产生数据,4个线程处理这些数据(可能是为了使用多核机器).如果您有一个庞大的全局数据池,那么当任何线程需要访问时,您可能必须锁定它,这可能会阻塞其他3个线程.随着您添加更多处理线程,您增加了锁定等待的可能性增加了可能需要等待的内容.最终添加更多线程无法实现,因为您所做的只是花费更多时间来阻止.

相反,如果您有一个线程将消息发送到消息队列,每个消费者线程一个,则它们不能相互阻塞.您必须在生产者和消费者线程之间锁定队列,但由于每个线程都有一个单独的队列,因此您有一个单独的锁,并且每个线程都无法阻止所有其他线程等待数据.

如果您突然获得32核计算机,则可以添加20个处理线程(和队列)并期望性能将相当线性地扩展,这与新线程将始终相互碰撞的第一种情况不同.


Eri*_*c Z 5

消息传递对于交换较少量的数据很有用,因为不需要避免冲突.实现比用于计算机间通信的共享内存容易得多.此外,正如您已经注意到的,消息传递的优势在于应用程序开发人员无需担心共享内存等保护的细节.

共享内存允许最大的通信速度和便利性,因为它可以在计算机内以内存速度完成.共享内存通常比消息传递更快,因为消息传递通常使用系统调用来实现,因此需要更耗时的内核干预任务.相反,在共享内存系统中,仅需要系统调用来建立共享内存区域.一旦建立,所有访问都被视为正常的内存访问,没有来自内核的额外帮助.

编辑:您可能希望实现自己的队列的一种情况是要生成和使用大量消息,例如日志记录系统.随着PostThreadMessage的实现,其队列容量是固定的.如果超出容量,消息将最容易丢失.