Главная » Просмотр файлов » С. Мейерс - Эффективный и современный C++

С. Мейерс - Эффективный и современный C++ (1114942), страница 26

Файл №1114942 С. Мейерс - Эффективный и современный C++ (С. Мейерс - Эффективный и современный C++) 26 страницаС. Мейерс - Эффективный и современный C++ (1114942) страница 262019-05-08СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 26)

(Про­стое действие, заключающееся в добавлении в функцию отладочного вывода для отладкиили настройки производительности может привести к таким проблемам, поскольку ин­струкции ввода-вывода в общем случае в соnst ехрr-функциях недопустимы.) Часть "гдеэто возможно" совета является вашей доброй волей на придание долгосрочного характе­ра данному ограничению на объекты и функции, к которым вы его применяете.Сл едует запомнить•Объекты const expr являются константными и инициализируются объектами, зна­чения которых известны во время компиляции.•Функции const expr могут производить результаты времени компиляции при вы­зове с аргументами, значения которых известны во время компиляции.•Объекты и функции constexpr могут использоваться в более широком диапазонеконтекстов по сравнению с объектами и функциями, не являющимися constexpr.•constexpr является частью интерфейса объектов и функций.3 .

1 0. Делайте константные функ ц ии-членыбезопасными в смысле потоковЕсли мы работаем в области математики, нам может пригодиться класс, представляю­щий полиномы. В этом классе было бы неплохо иметь функцию для вычисления корнейполинома, т.е. значений, при которых значение полинома равно нулю. Такая функция недолжна модифицировать полином, так что ее естественно объявить как const:class Polynomial {puЫic :11 Структура данных , хранящаяusing RootsTypestd : : vector<douЫe>; / / значения, где полином равен нулю3 . 1 О.Д елайте константные функции-члены безопасными в смысле потоков11111 ( см . "using" в разделе3 .

3)Roots'l'ype roots О conзt;};Вычисление корней - трудная дорогостоящая операция, так что мы не хотим их вы­числять до того, как они реально потребуются. Но если они нам требуются, то, опреде­ленно, требуются не один раз. Поэтому мы будем кешировать корни полиномов, еслинам приходится их вычислять, и реализуем roots так, чтобы функция возвращала кеши­рованное значение.

Вот как выглядит такой подход:class Polynomial {puЫic :using RootsTypestd: : vector<douЫe> ;RootsType roots ( ) constif ( ! rootsAreVa lid)rootsAreVa l id11 Если кеш некорректен,1 1 вычисляем корни и сохраняем11 их в in rootVa l st rue;return rootVa l s ;private :mutaЫe bool rootsAreValid{ fal s e } ; // См . инициализаторы11 в разделе 3 . 1mutaЫe RootsType rootVal s { } ;};Концептуально roots не изменяет объект Polynomial, с которым работает, но в качествечасти кеширующих действий может потребоваться изменение rootVal s и rootsAreVal id.Это классический случай использования mutaЫe, и именно поэтому эти данные-членыобъявлены с данным модификатором.Представим теперь, что два потока одновремен но вызывают roots для объектаPol ynomial:Polynomial р ;*// * ----- Поток 1 -auto rootsOfP : p .

roots ( ) ;---/ * ------- Поток 2 ---*/auto valsGivingZero : p . roots ( ) ;---Этот клиентский код совершенно разумен. Функция root s является константнойфункцией-членом, и это означает, что она представляет операцию чтения. Выполнениеопераций чтения несколькими потоками одновременно без синхронизации вполне без­опасно. Как минимум предполагается, что это так. В данном случае это не так, посколькув функции root s один или оба эти потока могут попытаться изменить члены-данныеroot sAreVal id и rootVa l s. Это означает, что данный код может одновременно читать1 12Гnава 3. Переход к современному С++и записывать одни и те же ячейки памяти без синхронизации, а это - определение гонкиданных. Такой код имеет неопределенное поведение.Проблема заключается в том, что функция roots объявлена как const, но не явля­ется безопасной с точки зрения потоков. Объявление const является корректным какв С++ l l , так и в С++98 (вычисление корней полинома не изменяет сам полином), так чтокоррекция нужна для повышения безопасности потоков.Простейший способ решения проблемы обычно один: применение rnutex:class Polynornia l {puЫ i c :std : : vector<douЫe > ;using RootsTypeRootsType roots ( ) const{std: : lock_guard<std : : mutex> g (m) ; 11 Блокировка мьютексаif ( ! root sAreValid) {1111Если кеш некорректенВычисление корней11Разблокированиеroot sAreValid = t rue ;return rootVals;private :IПUtaЫe std: : mutex m;mutaЬle bool rootsAreVa lid{ false } ;rnutaЬle RootsType rootVals { } ;};Мьютекс s t d : : mutex rn объявлен как rnutaЬle, поскольку его блокировка и разбло­кирование являются неконстантными функциями, а в противном случае в константнойфункции-члене roots мьютекс rn рассматривается как константный объект.Следует отметить, что поскольку s t d : : rnutex не может быть ни скопирован, ни пере­мещен, побочным эффектом добавления rn к Polynornia l является то, что Polynornial те­ряет возможность копирования и перемещения.В некоторых ситуациях мьютекс является излишеством.

Например, если все, что выделаете, - это подсчитываете, сколько раз вызывается функция-член, то часто более де­шевым средством является счетчик s t d : : atornic (т.е. счетчик, для которого гарантиру­ется атомарность операций - см. раздел 7.6). (Действительно ли это более дешевое сред­ство, зависит от аппаратного обеспечения и реализации мьютексов в вашей стандартнойбиблиотеке.) Вот как можно использовать std: : atornic для подсчета вызовов:11class PointpuЬli c :douЬle distanceFrornOrig in ( )const noexcept++callCount;3 .

1 О.Двумерная точка/ / См . описание noexcept// в разделе 3 . 8/ / Атомарный инкрементДелайте константные функции-члены безопасными в смысле потоков113return std : : hypot ( x , у ) ; // std: : hypot-новинкаC++ l lprivate :mutaЬle std : : atomic<ШlSigned> callCoшit{ О } ;douЫeх,у;1;Как и s t d : : rnutex, s t d : : at ornic невозможно копировать и неперемещать, так что нали­чие cal lCount в Point означает, что Point также невозможно и перемещать.Поскольку операции над переменными s t d : : a t ornic зачастую менее дорогостоящи,чем захват и освобождение мьютекса, вы можете соблазниться использовать s t d : : atornicбольше, чем следует.

Например, в классе, кеширующем дорогостоящее для вычислениязначение i n t , вы можете попытаться использовать вместо мьютекса пару переменныхstd : : atornic:class WidgetpuЬlic :int magicValue ( ) constif ( cacheValid) return cachedValue;else {auto val lexpensiveComputationl ( ) ;auto val2expensiveComputat ion2 ( ) ;cachedValue = vall + val2 ; / / Часть 1/ / Часть 2cachevalidtrue ;return cachedValue;===private :mutaЫe std: : atomic<Ъool> cacheValid{ false ) ;mutaЫe std: : atomic<int> cachedValue ;1;Этот способ работает, но иногда выполняет существенно большую работу, чем требу­ется. Рассмотрим такой сценарий.•Поток вызывает W i dget : : rna g i cValue, видит, что ca cheVa l i d равно f a l s e , вы­полняет два дорогостоящих вычисления и присваивает их сумму переменнойca chedVal ue.•В этот момент второй поток вызывает W i dge t : : ma g i cVa lue, также видит, чтозначение cacheVal id равно f a l se, а потому выполняет те же дорогостоящие вы­числения, что и только что завершивший их первый поток.

(Этот "второй поток"на самом деле может быть несколькими другими потоками.)Чтобы справиться с этой проблемой, можно пересмотреть порядок присваиваний зна­чений переменным cachedValue и cacheVa l i d, но вы вскоре поймете, что ( 1 ) вычислять114Гn а ва 3 . Переход к современному С++v a l l и v a l 2 перед тем, как cacheVa l i d устанавливается равным t rue, по-прежнему мо­гут несколько потоков, тем самым провалив цель нашего упражнения, и (2) на самомделе все может быть еще хуже:class WidgetpuЬli c :int magicValue ( ) constif ( cacheVa l id) return cachedValue ;else {auto val lexpens iveComputat ionl ( ) ;auto val2expensiveComputation2 ( ) ;/ / Часть 1cacheValid = true ;return cachedValuevall + val2 ; / / Часть 2===};Представим, что значение cacheVal id равно false.

Тогда возможно следующее.•Один поток вызывает W i dget : : magi cValue и выполняет код до точки, где пере­менная cacheVal i d устанавливается равной true.•В этот момент второй поток вызывает Widget : : magicValue и проверяет значениеcacheVal id.

Увидев, что оно равно t rue, поток возвращает cachedValue, несмотряна то, что первый поток еще не выполнил присваивание этой переменной. Такомобразом, возвращенное значение оказывается некорректным.Это неплохой урок. Для единственной переменной или ячейки памяти, требующей син­хронизации, применение std : : atomic является адекватным решением, но как толькоу вас имеется две и более переменных или ячеек памяти, которыми надо оперироватькак единым целым, вы должны использовать мьютекс. Для Widget : : magicValue это вы­глядит следующим образом:class WidgetpuЫic :int magicValue ( ) conststd : : lock_guard<std : : mutex>guard (m) ; / / Блокировка mi f ( cacheVal id) return cachedValue ;else {auto val lexpensiveComputa tionl ( ) ;auto val2expensiveComputation2 ( ) ;cachedValueval l + val 2 ;cacheVal id = true;===3.1 О.Де л айте константные функции-члены безопасными в смысле потоков115return cachedValue;private :mutaЫe std : : mutex m;mutaЫe int cachedValue ;mutaЫe bool cacheValid{ false ) ;);11Разблокирование m11Не атомарноеНе атомарное11Сейчас данный раздел основывается на предположении, что несколько потоков могут од­новременно выполнять константную функцию-член объекта.

Если вы пишете констант­ную функцию-член там, где это не так - т.е. там, где вы можете гарантировать, что этафункция-член объекта никогда не будет выполняться более чем одним потоком, - без­опасность с точки зрения потоков является несущественной. Например, совершенно не­важно, являются ли безопасными с точки зрения потоков функции-члены классов, раз­работанные исключительно для однопоточного применения. В таких случаях вы можетеизбежать расходов, связанных с мьютексами и std : : atomic, а также побочного эффекта,заключающегося в том, что содержащие их классы становятся некопируемыми и непере­мещаемыми.

Однако такие сценарии, в которых нет потоков, становятся все более ред­кими и, вероятно, дальше будут становиться только все более редкими. Безопаснее счи­тать, что константные функции-члены будут участвовать в параллельных вычислениях,и именно поэтому следует гарантировать безопасность таких функций с точки зренияпотоков.Сл едует запомн ить•Делайте константные функции-члены безопасными с точки зрения потоков,если только вы не можете быть уверены, что они гарантированно не будут ис­пользоваться в контексте параллельных вычислений.•Использование переменных std : : a t om i c может обеспечить более высокуюпо сравнен ию с мьютексами производительность, но они годятся толькодля работы с единственной переменной или ячейкой памяти.3 .1 1 .

Характеристики

Тип файла
PDF-файл
Размер
12,67 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6418
Авторов
на СтудИзбе
307
Средний доход
с одного платного файла
Обучение Подробнее