повышение ::unique_lock / upgrade_to_unique_lock

#boost #concurrency #locking #c 11

#повышение #параллелизм #блокировка #c 11

Вопрос:

Я проводил эксперименты с boost ::upgrade_to_unique_lock / unique_lock amp;amp; boost :: shared_lock, сценарий:

  • 1 напишите поток, в котором boost::unique_lock существует с boost::shared_mutex, в потоке я записываю в глобальный класс доступа

  • 3 потока чтения, каждый из которых имеет boost:: shared_lock с одинаковым boost:;shrared_mutex, у них есть цикл для чтения глобального класса доступа

Я заметил, что все потоки удерживают блокировки (1 уникальную, 3 общих) одновременно, и все они запускают циклы доступа к данным.

меня беспокоит то, что класс не является потокобезопасным, если я могу выполнять чтение / запись одновременно в разных потоках, чтение может завершиться сбоем. Даже если это не класс, мы используем примитивные типы, их чтение наверняка не приведет к сбою, но данные могут быть грязными, не так ли?

Комментарии:

1. Можете ли вы привести пример, который демонстрирует поведение, которое вы наблюдаете?

2. в моем опыте класс AClass равен std::string, в потоке чтения я распечатываю строку, в потоке записи я меняю строку на счетчик циклов (i), я вижу на экране, что строка постоянно меняется. Я уверен, что «они удерживают блокировки» — это объекты блокировки, находящиеся в той же области, что и цикл, всего на одну строку выше цикла.

3. Я думаю, что нашел проблему по своей вине, в потоке чтения я использовал безымянную блокировку, вот так: boost::shared_lock< boost::shared_mutex>(gmutex); теперь я меняю на boost ::shared_lock< boost::shared_mutex> xx (gmutex); это сработало!

4. У меня есть руководство по использованию shared_lock здесь: home.roadrunner.com /~ подсказка/мьютексы/блокировка.html#Общий . Эта ссылка включает реализацию, которая отличается от boost в области обновления. Я считаю, что реализация boost проекта обновления хуже (документирована по ссылке). Я пока не знаю, сталкиваетесь ли вы с проблемами, которые мог бы исправить мой дизайн. Я публикую в надежде помочь вам и выяснить, где находится путаница.

5. Это было бы хорошей ошибкой для перехвата во время компиляции, но я не знаю как.

Ответ №1:

 boost::shared_lock<boost::shared_mutex>(gmutex);
  

Это не «безымянная блокировка». Это создает временный shared_lock объект, который блокируется gmutex , затем этот временный shared_lock объект уничтожается, разблокируясь gmutex . Вам нужно назвать объект, сделав его переменной, например:

 boost::shared_lock<boost::shared_mutex> my_awesome_lock(gmutex);
  

my_awesome_lock затем будет уничтожен в конце блока, в котором он объявлен, что является желаемым поведением.