Существует 2-резьбовое приложение; Поток GUI добавляет задачи, рабочий поток обрабатывает их. Однако иногда Q_ASSERT обнаруживает ложную задачу.QThread занимает некоторое время, чтобы проснуться?
Итак, вопрос: возможно ли, что
- Thread 1 запирает мьютекс, устанавливает _hasTask истина, вызывает wakeAll, и разблокирует мьютекс,
- _hasTaskCondition запомнит, что он должен проснуться, но не имеет времени для блокировки мьютекса, потому что
- Тема 1 снова вызывает addTask с ложным аргументом, блокирует мьютекс, устанавливает _hasTask в false, не вызывает wakeAll сейчас, разблокирует мьютекс.
- Итак, теперь Thread 2 имеет _hasTask == false, но поток проснулся, блокирует мьютекс и обрабатывает задачу => стрела.
Некоторые отладки (MSVC 2013) показывают, что это может произойти. Если Qt не допускает такой сценарий, то что, вероятно, происходит здесь?
упрощенный код, чтобы проиллюстрировать логику:
Class работник, переменные члены:
unsigned int _taskData; // init with 0
QMutex _mutex;
QWaitCondition _hasTaskCondition;
резьбы 1 (GUI QThread):
резьбы 2 (рабочий 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
}
}
Как здесь, с Pthreads: HTTP: // StackOverflow .com/questions/4544234/call-pthread-cond-signal-without-locking-mutex –
Но в примере Qt такой цикл отсутствует: http://qt-project.org/doc/qt-4.8/qwaitcondition.html –
Это как раз идиома для переменных ожидания, вы блокируете и начинаете проверять проверку вашей переменной в цикле и ждать состояния в теле цикла. –