#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
затем будет уничтожен в конце блока, в котором он объявлен, что является желаемым поведением.