2

我有一个关于线程间通信的一般问题。

现在我正在使用一堆 C++ 线程(~15)。

他们都在使用 BusyWait(轮询)彼此来获取要处理的数据。但是很难保持较低的 CPU 使用率 && 提供良好的性能并避免进行过多的上下文切换。

所以我正在查看条件变量和信号。我想我理解线程进入 .Wait() 的一般概念,等待另一个线程调用 .Signal()。

问题#1)我的问题可能是概念性的,但是如果等待信号的线程在等待时被挂起,它自己就无法执行任何操作。反正有没有让它自己醒来执行一些动作。

问题 #2)此外,我的课程用于双向传递数据。但是如果中间类正在等待另一个类的信号,它就无法向那个类发送信号。如:

 _________                       _________                       __________
| Class A |---newData Signal--->| Class B |---newData Signal--->| Class C  |
|         |                     |(WAITING)|<---newData Signal---|          |
 ---------                       ---------                       ----------

因此,如果 B 类为来自 C 的 .Signal() 开启 .Wait(),则它无法处理来自 A 的新信号。

A && C 是否有可能发送相同的“newData”信号 B 来唤醒它?是否有可能将信号与 A && C 区分开来。

我正在使用 C++ 使用 ACE 框架进行编码,并且可能会切换到 Boost。但我想这足够通用,我可以将答案应用于任何操作系统(希望如此)。

谢谢

4

5 回答 5

2

如果您希望父线程在子线程运行时工作,您可以等待超时信号。每次超时到期时,您都会做一些工作并再次等待。

于 2009-06-04T12:49:06.567 回答
1

问题 #1)在大多数实现中,您可以限制最大等待时间,因此说:等待 2 秒,然后做某事并再次等待。

问题 #2)在大多数实现中,您可以一次等待多个信号。您可以说:如果信号 A 或 B 被触发,则唤醒。

于 2009-06-04T12:54:31.160 回答
0

您寻求的答案非常复杂,并且此 wiki 上的空间还不足以解决所有问题:(

你需要做的是给自己找一些很好的网站来解释线程是如何工作的。您所追求的大部分内容都可以通过正确的设计来完成,但您首先需要更好地理解这些概念。

为了使您的通信顺利进行,您需要将信号发送到正确的位置并等待正确的事件。

最简单的方法是使用所有线程共享的单个条件变量,这将使您获得比轮询更好的效果。当这种情况发出信号时,他们都会醒来并寻找一些工作要做。

这效率不高,但很简单,对你有用,而且比轮询更有效。一旦你完成了这项工作,你可以尝试引入一些新的条件变量并拆分哪些线程等待哪些线程——这样做时你会犯很多错误并遇到很多死锁和饥饿。坚持下去,您将开始了解这一切是如何运作的。

祝你好运。

于 2009-06-04T12:54:33.747 回答
0

假设您有某种方法可以进行临界区锁定(例如 java 同步)或线程安全队列,您可以使用运行队列。

对于每个线程,修改/覆盖睡眠实现,以便当线程等待时,它将自己添加到运行队列的末尾。

假设一次只应该运行一个线程,当前运行的线程在它本身进入睡眠/等待之前应该做的最后一件事是唤醒列表头部的线程。

如果您需要更复杂的线程执行/调度,下一步是创建一个遍历队列的调度程序线程,调整队列中线程的顺序,检查哪个线程拥有运行所需的所有资源等.

于 2009-06-04T13:31:03.923 回答
0

尽管您可以为此使用条件变量,但问题描述建议改用消息队列。然后,线程 A 和线程 C 可以向 B 的队列中注入消息,B 进行相应的处理。(当然,为了区分两个线程,你应该安排 A 和 C 发送不同的消息。)

我不知道 ACE 对消息队列有什么支持,但是,在(比如说)Java 并发框架中,您可以使用ConcurrentLinkedQueue. :-)

于 2009-06-04T13:01:02.517 回答