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