2013-07-29 112 views
-1

我想设计一个多线程应用程序,它执行以下操作: 一个线程按顺序写入循环缓冲区。然后将有n个读写器线程等待由写线程发起的某个信号唤醒并从循环缓冲区中读取。该信号应该以某种方式包含一个整数值,该值表示要读取的循环缓冲区偏移量。这可能在C++中做到吗? 任何帮助,将不胜感激。多线程信号

因为我想要一个能够尽可能接近高速实时流量的设计,所以我想要消除内存的任何分配/释放。所以循环队列将是启动时分配的连续内存块。我不确定你提到的排队是否符合这一点。

生产者只需要跟踪每次写入字节时从哪里开始写入字节的循环缓冲区数组。 所以我真正要求的是制作者在完成写入事件时传播“信号”的方式,该事件包含写入循环缓冲区的最后一个字节的位置(偏移量)。这将避免需要锁定机制。

当接收到“传播”信号/事件时,消费者线程将醒来。他们本身只需要跟踪他们离开的位置,然后只读取信号偏移值。最后,生产者和消费者当然需要知道循环缓冲区从何处开始,它有多大,以便他们知道何时进行包装。

+0

是的,这是可能的。 –

+1

你应该向我们展示你的尝试,并描述它的行为如何偏离你的期望。 – andand

回答

0

根据您最近的编辑,我会建议使用有界的队列。

一个有界的队列是一个具有特定长度的队列,因此队列在开始时被全部分配,并且所有元素都将基于元素的默认构造函数进行初始化,或者为null,无论您想要什么它是。

从生产者方面来看:如果队列未满,则将一个元素push_back到队列中。

来自消费者方:如果队列不为空,则从队列中弹出一个元素并处理它。

您不需要通过这种方式在您的生产者和消费者之间发送消息。事实上,让你的各种线程以某种方式进行沟通会产生很多开销,而这些开销只会随着更多的线程变得更加复杂。

队列本身需要是线程安全的,并且有关于如何在C++中创建线程安全有界队列的示例。

编辑:

你可以把你在队列中呼风唤雨。我会在你的情况下建议一个指针队列,因为指针的大小在整个执行过程中将保持不变。这使您可以预先分配队列,但意味着您必须在运行时分配数据报。

您对线程安全的想法或多或少都是如此。在某些情况下,多线程访问单个变量是很好的 - 通常在他们不修改变量时,只是读取它。即使您使用的是循环缓冲区,循环缓冲区也必须是线程安全的,因为任何两个生产者或使用者都将更改循环缓冲区。这就是说,每个线程访问您的循环缓冲区或队列所需的时间将会非常小 - 它应该有足够的时间将信息复制到数据结构中或从数据结构中复制出来,就是这样。您可以在不锁定其他线程的数据结构的情况下完成对数据的所有其他计算。

如果您想让多个线程一次访问数据,您可能需要考虑创建多个队列或缓冲区。也许每个生产者/消费者对有一个循环缓冲区,或者每个输入流有一个队列......无论它发生什么。没有更具体的例子很难说。

编辑2

Here's a link to a thread-safe queue。我不确定它是否会有所帮助,但看起来很有希望。

+0

排队的项目可以是不同的长度,即数据报?另外,从我理解的线程安全意味着一次只有一个线程可以在队列上运行。尽管有点复杂,但我努力的方法并没有这种限制。 –

+0

@AlKurlansky我编辑了我的答案。 – Shaz

+0

最后一次交流有很大帮助。有界队列方法很有意义。现在我需要使用一个等待队列不为空的方法的队列类。一个生产者/一个消费者模型将为我工作。我不需要在运行时分配数据报。在启动时,我只需要创建一个大的连续内存块,然后将数据流传输到它,在需要时进行换行等。每个排队的项目都将指向循环缓冲区中的下一个数据报,并且它们可以处理数据报地点。我可以通过反复试验来计算出circ buff的大小。 –

2

这就是国际海事组织,这是一种糟糕的做事方式。让制作人简单地将项目添加到循环缓冲区。让每个阅读器在循环缓冲区中等待非空。非空时,阅读器线程只是将下一个项目从缓冲区中移除并进行处理。缓冲区本身应该跟踪偏移等事情。

至于为什么这样更好:主要是因为它让系统的每个部分都可以自己完成自己的事情,并且与系统的其他部分进行最少的交互。

当你描述系统时,生产者需要知道队列的内部细节,以及消费者线程的基本上所有细节(在任何给定的时间唤醒哪些细节,任何给定的时间,要安排执行任何特定的任务等)

我建议最小化的设计保持生产者致力于生产。它的只有关于系统其余部分的知识由一件事情组成:一旦产生它们,如何将任务放入队列中。

同样,消费者线程只需要知道如何从队列中获取任务,以及如何执行该任务。

队列本身负责所有需要的线程同步。仅当任务从队列中被移入/移除时才需要同步。队列本身是相当可重用的(几乎可以用于这种生产者 - 消费者情况)和可替换的(例如,基于锁和无锁实现之间的相当平凡的切换)。

线程调度留给操作系统 - 空闲的使用者线程只需在队列中等待,然后操作系统决定要唤醒哪一个来执行特定的任务。如果它们当前都不处于空闲状态,则操作系统也已经“知道”了这一点,并让它们执行当前处理,直到完成并再次等待队列。

总结:你的建议使得系统的三个部分都变得更加复杂。更糟糕的是,它与三者交织在一起,所以很难与其中任何一个部分隔离开来。

采用这种设计,在设计的每个部分基本保持简单,他们每个人都从其他相当孤立,所以每个人都可以从别人的工作,思索,等等,在隔离。

+0

如果你说某件事情是一种糟糕的做事方式,那么如果你支持这一点并解释你为什么这么想,那将是有益的。 –