QThread需要一些时间才能醒来?

时间:2014-10-22 14:55:00

标签: c++ multithreading qt

有一个2线程的应用程序; GUI线程添加任务,工作线程处理它们。 但是,有时Q_ASSERT会检测到错误的任务。

所以问题是:是否可能,

  1. 线程1锁定互斥锁,将_hasTask设置为true,调用wakeAll,并解锁互斥锁,
  2. _hasTaskCondition记住它应该唤醒,但没有时间锁定互斥锁,因为
  3. 线程1再次使用false参数调用addTask,锁定互斥锁,将_hasTask设置为false,不立即调用wakeAll,解锁互斥锁。
  4. 所以现在线程2有_hasTask == false,但线程被唤醒,锁定互斥锁并处理任务=>热潮。
  5. 一些调试(MSVC 2013)表明它可能发生。 如果Qt不允许这样的情况,那么可能会发生什么呢?


    用于说明逻辑的简化代码:

    类工作者,成员变量:

    unsigned int   _taskData;   // init with 0
    QMutex         _mutex;
    QWaitCondition _hasTaskCondition;
    

    线程1(GUI QThread):

    // Called from time to time, sometimes very often
    // input > 0 - to wake worker thread to process some work, 
    // input == 0 - to put worker thread to sleep on next iteration
    
    void Worker::addTask(unsigned int taskData)
    {
        QMutexLocker lock(&_mutex);
        if (taskData == _taskData)
            return;
        _taskData = taskData;
        if (_taskData > 0)
            _hasTaskCondition.wakeAll();
    }
    

    线程2(worker QThread):

    // In a loop state
    
    void Worker::doWork()
    {
        unsigned int currentTaskData = 0;
        while (true)
        {
            _mutex.lock();
            if (_taskData == 0)
                _hasTaskCondition.wait(&_mutex);
    
            Q_ASSERT(_taskData > 0); // error at some moment
    
            // copy task to process it without locking the mutex
            currentTaskData = _taskData;
            _taskData = 0;
    
            _mutex.unlock();
    
            // Process currentTaskData:
            // some useful work without touching
            // _hasTask, _mutex and _hasTaskCondition variables
        }
    }
    

1 个答案:

答案 0 :(得分:0)

将if更改为while:

while(_taskData == 0)
    _hasTaskCondition.wait(&_mutex);

然后当wakeAll发生时,线程将重新检查它是否确实有任务然后继续等待