QReadWriteLock рекурсия
Я использую QReadWriteLock в рекурсивном режиме.
Этот код сам по себе не имеет смысла, но у меня возникают следующие проблемы:
lock->lockForWrite();
lock->lockForRead();
lockForRead заблокирован. Обратите внимание, что это в рекурсивном режиме.
Я вижу, что запись - это "превосходящая" блокировка, она позволяет мне читать и записывать защищенные данные, а блокировка чтения позволяет только чтение.
Кроме того, я думаю, что блокировка записи не должна быть заблокирована, если единственный читатель - тот же, который запрашивает блокировку записи.
Из исходных кодов qreadwritelock.cpp я вижу, что нет никаких попыток заставить его работать так, как мне бы хотелось. Так что это не ошибка, а функция, которую я считаю отсутствующей.
У меня вопрос такой: должна ли быть разрешена такая рекурсия? Есть ли какие-либо проблемы, которые возникают из-за такой реализации и какими они будут?
2 ответа
Обратите внимание, что тип блокировки не может быть изменен при попытке рекурсивной блокировки, т.е. невозможно заблокировать чтение в потоке, который уже заблокирован для записи (и наоборот).
Итак, как вы говорите, это так, как это работает. Лично я не понимаю, как разрешение чтения в том же потоке, что и запись, заблокированная для записи, может вызвать проблемы, но, возможно, это требует неэффективной реализации блокировки?
Вы можете попробовать задать вопрос на форумах QT, но я сомневаюсь, что вы получите окончательный ответ. Почему бы вам не взять исходный код QT как стартер и попробовать себя, если это то, что вам нужно. Написание объектов синхронизации может быть сложным, но это хорошее учебное упражнение.
Я нашел этот вопрос, когда сам искал ту же функциональность. Размышляя о реализации этого самостоятельно, я понял, что определенно возникает проблема, возникающая при этом:
Таким образом, вы хотите обновить блокировку с общего (чтение) до эксклюзивного (запись). дела
lock->unlock();
lock->lockForWrite();
это не то, что вам нужно, поскольку вы не хотите, чтобы другой поток получил блокировку записи сразу после того, как текущий поток снял блокировку чтения. Но если бы был
lock->changeModus(WRITE);
или что-то подобное, вы создадите тупик. Чтобы получить блокировку записи, блокировка блокируется до тех пор, пока не будут сняты все текущие блокировки чтения. Поэтому здесь несколько потоков будут блокировать ожидание друг друга.