【发布时间】:2019-11-22 08:58:37
【问题描述】:
我有一个这样的程序结构:一个线程接收任务并将它们写入输入队列,多个线程处理它们并写入输出队列,一个响应结果。当队列为空时,线程会休眠几毫秒。队列里面有互斥体,push 做 lock(),popping 做 try_lock(),如果队列中没有任何内容则返回。
这是处理线程例如:
//working - atomic bool
while (working) {
if (!inputQue_->pop(msg)) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
continue;
} else {
string reply = messageHandler_->handle(msg);
if (!reply.empty()) {
outputQue_->push(reply);
}
}
}
我不喜欢的是,从收到任务到响应的时间,正如我用 high_resolution_clock 测量的那样,几乎是 0,此时没有睡眠。当有睡眠时,它会变得更大。 我不希望浪费 cpu 资源并想做这样的事情:当接收线程获取任务时,它通知一个处理线程,它执行 wait_for,当处理任务完成时,它以相同的方式通知响应线程。因此,我认为我会花费更少的时间,并且不会浪费 cpu 资源。我有一些问题:
- 这会按我认为的方式工作吗,唯一的区别是在通知时醒来?
- 为此,我必须创建 2 个条件变量:第一个相同用于接收线程和所有处理,第二个相同用于所有处理和响应?处理线程中的互斥锁必须对所有线程都是通用的还是唯一的?
- 我可以在 if 分支中创建 unique_lock(mutex) 和 wait_for() 来代替 sleep_for 吗?
- 如果某些处理线程很忙,是否可能 notify_one() 可以尝试唤醒其中一个,但不能唤醒空闲线程?我需要使用 notify_all() 吗?
- 是否有可能 notify 不会唤醒任何线程?如果有,概率大吗?
【问题讨论】:
-
你有没有想过使用带有轮询机制的消息队列而不是调用
std::this_thread::sleep_for?这样,您的线程仅在有要处理的事件时才会唤醒。一个伟大的消息队列的例子是ZeroMQ -
std::condition_variable的方法对我来说似乎是合理的。生产者必须锁定/修改/解锁/通知,消费者必须锁定/等待/解锁。如果你有一个线程“管道”,那么中间的线程既是消费者也是生产者。因此,它必须同时实现。 -
如果某些处理线程很忙,notify_one() 是否可以尝试唤醒其中一个 :-) 一个忙线程不在队列中操作系统选择一个唤醒。我没有看到这个问题。另一个话题,我曾经偶然发现:如果所有消费者都很忙,通知会发生什么?我得出的结论是,通知只是“无处可去”,但不会造成任何伤害。并且不要忘记可能会有“spurios 唤醒”......
-
是否有可能notify 不会唤醒任何线程? 如果有等待线程,notify 应该唤醒一个或全部。如果不是这样,整个
condition_variable事情就会被打破,恕我直言。我假设condition_variable是建立在信号量之上的。如果它们不能按预期工作,我会认真考虑切换到另一个操作系统。 ;-)
标签: c++ multithreading