我有一个相当简单的情况:我在一个线程中有一个高速数据生成器,它生成一个带有[变长度]元素的缓冲区。填充此缓冲区后,我有一个将其写入磁盘的消费者。
现在,如果缓冲区还没有被消费者线程写入,那么生产者线程需要回到生成ASAP,它就会旋转到位:
int volatile datatogo=0; // global with starting condition
while(datatogo != 0) // spin, buffer not yet written out
{
if (recflag == 0) return; // recording is terminated
}
// clipped code fills buffer, then:
datatogo = lengthoffill;
...在另一个线程中,缓冲区编写器执行此操作:
while(recflag)
{
if (datatogo)
{
if (m_File.write(sbuffer,datatogo) == -1)
{
recflag=0; // bail NOW
}
datatogo = 0; // buffer transferred
}
usleep(100); // 100 uS
}
这样做的最终结果是写入磁盘消费者在完成写入时放弃CPU,知道生产者必须花一些时间来实际填充缓冲区。当消费者在没有数据时睡着了,CPU可供生产者使用。消费者睡眠时间为100 uS,检查数据,如果没有,则返回睡眠状态,因此除了睡眠状态之外,它在该状态下没有做太多事情。
然而,因为睡眠时间是任意的,所以这不可能是最佳的;即使我仔细调整它以在我的机器上工作(8核,3 GHz),它在另一台机器上的行为也会不同。有时会有数据准备好被写入,消费者刚刚进入睡眠状态,将整个100美元扔出窗外,可以这么说。我也对这样一个小时间窗口的分辨率和可靠性有疑虑 - 而较大的窗口将不起作用。
因此。 Qt中有多种机制来控制对事物的访问,这基本上就是我想做的事情。但我不明白哪一个(如果有的话)会做我想做的事,那就是:
1)让消费者睡眠,直到缓冲区已满,然后写入并返回睡眠状态,或直到作业停止,这样它就可以关闭文件(它可以检查唤醒时哪个)
2)生成器只在缓冲区被写出时才会休眠,否则填充缓冲区并返回生成其内容。
我需要尽可能多的CPU可用 - 这是一个软件定义的无线电应用程序,有数据飞来飞去,运行多个FFT,各种图形发生,等等。旋转时间很糟糕,很糟糕
某种灵魂可以指向我理想的Qt机制吗?我发现QMutex,QWaitCondition,QSemaphore上的Qt文档有点不透明。
答案 0 :(得分:5)
标记整数变量volatile不足以满足多线程程序的要求:
Why is volatile not considered useful in multithreaded C or C++ programming?
如果你想要了解螺母和螺栓,你可以使用原子整数和指针:
http://doc.qt.io/archives/qt-4.7/qatomicint.html
http://doc.qt.io/archives/qt-4.7/qatomicpointer.html
但你确实想要使用Qt的线程原语。与使用互斥锁,信号量和等待条件相比,旋转/睡眠是浪费的。这些是你在任何线程库中都能找到的相当一般的概念,所以我会四处寻找它们的好解释。一开始不是很容易把头包起来,但是人们需要知道它!
QWaitCondition的生产者/消费者示例应该适用于您的场景:
http://doc.qt.io/qt-4.8/qt-threads-waitconditions-example.html