Qt: QReadWriteLock работает как показано? - PullRequest
0 голосов
/ 14 декабря 2010

У меня есть четыре потока, которые должны быть синхронизированы. Для этого я хочу передать каждому потоку один и тот же массив bool. Каждый поток изменит «соответствующее» значение на true, как только достигнет определенной точки в потоке, а затем постоянно проверяет, являются ли остальные значения истинными. Если это так, введите цикл ... Пример

//above thread init stuff
oLock->lockForWrite();
abSync[iThreadNum] = true;  //iThreadNum = {0...3} depending on whats set
oLock->unlock();

bool bSynced = false;
while (!bSynced)
{
    oLock->lockForRead();
    if (abSync[0] && abSync[1] && abSync[2] && abSync[3])
        bSynced = true;
    oLock->unlock();
}

//below thread run and finish

Работает ли QReadWriteLock, как описано выше? Будет ли он фактически блокировать переменную для записи (по мере прохождения каждого потока), но не для чтения? быстрый просмотр документации показывает, что QReadWriteLock будет блокироваться только на lockForRead(), если есть блокировка записи, но не блокировка чтения, как я и хотел выше.

Кроме того, я понимаю, что вышесказанное будет отсасывать циклы ЦП по мере прохождения цикла, и это требуемое поведение. Использование Sleep недостаточно достаточно для наших нужд.

Ответы [ 3 ]

3 голосов
/ 14 декабря 2010

Нет, QReadWriteLock не делает именно то, что вы хотите, после прочтения вашего комментария, приведенного выше, вам действительно не нужна блокировка для записи данных, вам просто нужно убедиться, что чтения являются массивными в вашем массиве. Если вам нужно, чтобы потоки запускались одновременно, почему бы не выполнить обратный отсчет? Это гарантирует, что все потоки (возможно) запускаются одновременно.

2 голосов
/ 14 декабря 2010

Я не знаю, какой у вас запас для "одновременной работы", но потоки не работают одновременно, и трудно предсказать, какие будут смещения. То, чего вы пытаетесь достичь, - это барьер потоков , который должен быть сделан с помощью условных переменных ( QWaitCondition ), но даже это не гарантирует одновременный запуск, только то, что они выиграли не начинайте, пока все не закончили предыдущую работу (но это может быть хорошо, если ваш запас достаточно велик).

1 голос
/ 15 декабря 2010

Я предполагаю, что требование здесь выглядит примерно так:

// each thread intends to do this
doStep1();
makeSureEveryOtherThreadHasDoneStep1();
doStep2();

Я также предполагаю, что на самом деле не имеет значения, все ли «1004» работают одновременно или нет, до тех пор, пока каждый из doStep2() работает после всех doStep1() s завершено.

При этих двух предположениях код, указанный в вопросе, выглядит правильно, но использует напряженное ожидание. Лучшим решением было бы использовать QWaitCondition с QMutex. Что-то вроде:

doStep1();
mutex->lock();
abSync[iThreadNum] = true;
if (abSync[0] && abSync[1] && abSync[2] && abSync[3]) {
    waitCondition->wakeAll(); // yay! all are in sync
} else {
    waitCondition->wait(mutex);
}
mutex->unlock();
doStep2();

Отредактировано: mutex->unlock() перемещено с сразу после wakeAll() до doStep2() в комментариях ниже, благодаря @ stefaanv.

...