c++ - 为什么我在使用 qt 等待条件时不必包含锁定/解锁语句?

标签 c++ multithreading qt

我非常了解多线程,尽管非常头疼,但我仍然觉得它非常迷人。我正在使用 qt 并一直在研究教程,发现一个完全适用于我的情况,它将数据流式传输到循环缓冲区中,一个线程写入其中,一个线程从中读取。这是教程here .首先让我问你我是否在等待条件下选择了正确的方法。

我选择不使用信号量,因为缓冲区的大小可能随时从主线程更改,从而导致重新分配和重新调整读/写索引,并且调整信号量的大小似乎并不那么容易。我不想在循环中放置一个 if 比较来判断是否执行循环体,因为它必须一遍又一遍地执行,直到它可以在缓冲区中容纳更多数据,所以等待条件是我的自然解决方案.

其次,我对他们示例中等待条件的作用感到有点困惑。看起来他们锁定了互斥量,检查等待条件并阻塞,在满足条件时继续,然后就在那里解锁互斥量。这是否意味着此时对用于写入的缓冲区的访问完全不 protected ?

第三,当我的主线程想要停止时,我对如何结束这些线程有点不知所措。我不能使用等待条件,因为我希望它们在主线程希望的时间内运行,而且我不认为我可以跨线程发出信号来告诉它退出。通知线程停止执行的唯一方法是在某个地方放置一个 if 不断检查每个循环中位于主线程中的 bool,然后等待线程在析构函数中退出吗?问题是在等待条件下,我必须首先将 bool 设置为退出,然后唤醒两个线程。我真的很困惑在这里做什么,任何建议都将不胜感激。

最佳答案

缓冲区访问受数据索引选择方式的保护:

  1. 消费者在缓冲区中看不到任何数据,因此阻塞
  2. 生产者发现缓冲区未满,因此在索引 0
    的缓冲区中写入一些数据 并唤醒消费者并增加索引 t write at index 1
  3. 消费者看到数据并读取索引 0

特别是在临界区之间来自消费者的 i % buffersize 与来自生产者的 i % buffersize 相同的唯一方法是如果 numUsedBytes = = 0 并且您是生产者或 numUsedBytes == buffersize 并且您是消费者

看到这里你应该能够推断生产者和消费者都不能同时读取或写入同一个索引:因此访问是 protected

这个solution is well researched

虽然这个实现有几个问题:如果条件因任何原因被唤醒,if 检查是不够的。他们应该使用 QMutexLocker所以异常或提前返回不会搞砸一切:

{
    QMutexLocker lock(mutex.lock());
    while (numUsedBytes == BufferSize)
    {
         bufferNotFull.wait(&mutex);
         if(shouldStop)return;
    }
}

关于c++ - 为什么我在使用 qt 等待条件时不必包含锁定/解锁语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20144933/

相关文章:

c++ - 运算符在命名空间中的类之外重载

ruby - 线程对这种情况有益吗?

c++ - Qt:在 child 之前捕获事件

c++ - 优化 QPixmap 绘图

c++ - 类中的递归函数或竞争条件?

C++0x 模板函数对象推断

c++ - yaml-cpp 解析嵌套映射和序列错误

java - 是否值得清理 Filter 中的 ThreadLocals 来解决与线程池相关的问题?

有界队列的 Java 线程池

database - Qt SQLITE 查询 QVariant 无效