1

我有一个相当简单的情况:我在一个线程中有一个高速数据生产者,它生成一个包含[可变长度]元素的缓冲区。一旦这个缓冲区被填满,我就有一个消费者将它写入磁盘。

现在,如果缓冲区尚未被消费者线程写入,则需要尽快恢复生产的生产者线程会旋转到位:

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 uS 扔出窗外。我也对如此小的时间窗口的分辨率和可靠性感到不安——而更大的窗口将无法工作。

所以。Qt中有多种机制可以控制对事物的访问,这本质上是我想要做的。但我不明白哪一个(如果有的话)会做我想做的事,那就是:

1)让消费者睡眠直到缓冲区已满,然后写入并重新进入睡眠状态,或者直到作业停止以便它可以关闭文件(它可以在唤醒时检查哪个)

2) 当生产者睡眠时,仅当缓冲区被写出时,否则填充缓冲区并返回生产其内容。

我需要尽可能多的可用 CPU ——这是一个软件定义的无线电应用程序,到处都有数据飞来飞去,多个 FFT 正在运行,各种图形 hoo-ha 发生等等。旋转时间很糟糕,很糟糕。

有什么好心人能指点我使用的理想 Qt 机制吗?我发现 QMutex、QWaitCondition、QSemaphore 上的 Qt 文档...有点不透明。

4

1 回答 1

5

将整数变量标记为 volatile 不足以保证您在多线程程序中需要:

为什么 volatile 在多线程 C 或 C++ 编程中没有用?

如果您喜欢深入了解具体细节,实际上可以使用原子整数和指针:

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

于 2012-04-17T16:43:44.380 回答