0

应用程序设计

我有一个 C++ 应用程序,它有一个生产者线程、多个队列(在运行时创建)和消费者线程。

生产者线程通过 Tcp/Ip 获取数据并放入相应的队列(例如,如果数据是 A 类型并放入队列 A)。

消费者线程当前从 1 - n 循环队列以处理来自每个队列的数据。

根据要求,无需跟踪上次更新或最少更新的队列。只要更新了任何队列,消费者就应该处理 1 - n 个队列。

如果任何队列的大小超过定义的限制,生产者线程将在插入新项目之前弹出第一个项目(以管理队列大小)。

线程之间的资源同步和信令:

在这个实现中,消费者线程应该休眠,直到没有队列有来自侦听器的数据。只有当生产者将数据放入任何一个队列时,消费者线程才应该唤醒。

使用互斥锁在 2 个线程之间同步多个队列。每当生产者将数据放入任何队列时,都会在线程之间实现事件信号以唤醒消费者线程。

然而,这种唤醒消费者线程的信号方式,尽管任何队列中有数据,消费者仍有可能进入睡眠状态。

问题:

让我们以这种情况为例,考虑消费者正在处理第 n 个队列的数据;同时,生产者有可能将数据放入 n-1、n-2 队列中,并且由于消费者处于清醒状态并正在处理第 n 个数据,因此信令无效。一旦消费者完成第 n 个队列数据的处理,它将进入休眠状态,并且在侦听器发出任何进一步的信号之前,不会处理 n-1、n-2 中的数据。

我们如何解决这种情况?人们还建议使用信号量。信号量与这种情况相关吗?

提前致谢。

4

3 回答 3

4

这是 C++11 的经典示例std::condition_variable

在这种情况下,条件是消耗性资源的可用性。如果消费者线程耗尽工作,他wait就在条件变量上,这实际上使他进入睡眠状态。notify每次插入队列后的生产者。必须小心安排锁定,以使队列上的争用保持最小,同时仍然避免消费者错过通知并进入睡眠状态的情况,尽管工作可用。

于 2013-09-17T10:51:26.920 回答
1

信号量会起作用,是的。

但我不完全确定它是否有必要。听起来您的问题纯粹是因为消费者线程在处理队列 N 后无法环回。它应该在连续看到 N个队列后进入睡眠状态,同时持有一个互斥锁以确保在与此同时。

当然,一直持有该互斥锁是大材小用。相反,您应该继续循环,一一清空队列并计算您看到的空队列数量。一旦您连续看到 N 个空队列,请使用互斥锁,这样您就知道不能添加新条目,然后重新检查。

它确实取决于您的信号机制。强大的信号机制允许您在线程进入对该信号的检查之前发出信号。这是必要的,因为否则您会遇到竞争条件。

于 2013-09-17T10:52:09.153 回答
0

您可以select在由信号 -> 生成的文件描述符上使用并等待它,因此它可以等待超时(选择有它们)并在收到信号时唤醒(信号必须被屏蔽和阻塞)。当signalfd(look man signalfd) 可读时,您可以从中读取 astruct signalfd_siginfo并检查ssi_signo信号编号(如果它是您用于通信的信号编号)。

于 2013-09-17T11:20:04.003 回答