Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ

Тут можно читать онлайн Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство ДМК Пресс, год 2012. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Параллельное программирование на С++ в действии. Практика разработки многопоточных программ
  • Автор:
  • Жанр:
  • Издательство:
    ДМК Пресс
  • Год:
    2012
  • Город:
    Москва
  • ISBN:
    978-5-94074-448-1
  • Рейтинг:
    5/5. Голосов: 11
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 100
    • 1
    • 2
    • 3
    • 4
    • 5

Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ краткое содержание

Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - описание и краткое содержание, автор Энтони Уильямс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru
В наши дни компьютеры с несколькими многоядерными процессорами стали нормой. Стандарт С++11 языка С++ предоставляет развитую поддержку многопоточности в приложениях. Поэтому, чтобы сохранять конкурентоспособность, вы должны овладеть принципами и приемами их разработки, а также новыми средствами языка, относящимися к параллелизму.
Книга «Параллельное программирование на С++ в действии» не предполагает предварительных знаний в этой области. Вдумчиво читая ее, вы научитесь писать надежные и элегантные многопоточные программы на С++11. Вы узнаете о том, что такое потоковая модель памяти, и о том, какие средства поддержки многопоточности, в том числе запуска и синхронизации потоков, имеются в стандартной библиотеке. Попутно вы познакомитесь с различными нетривиальными проблемами программирования в условиях параллелизма.

Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - читать онлайн бесплатно полную версию (весь текст целиком)

Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - читать книгу онлайн бесплатно, автор Энтони Уильямс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Листинг 3.9.Применение std::lock()и std::unique_guardдля реализации операции обмена

class some_big_object;

void swap(some_big_object& lhs,some_big_object& rhs);

class X {

private:

some_big_object some_detail;

std::mutex m;

public:

X(some_big_object const& sd): some_detail(sd) {}

friend void swap(X& lhs, X& rhs) {

if (&lhs == &rhs) std::defer_lock оставляет

return; мьютексы не захваченными (1)

std::unique_lock lock_a(lhs.m, std::defer_lock);←┤

std::unique_lock lock_b(rhs.m, std::defer_lock);←┘

std::lock(lock_a, lock_b); ← (2) Мьютексы захватываются

swap(lhs.some_detail, rhs.some_detail);

}

};

В листинге 3.9 объекты std::unique_lockможно передавать функции std::lock() (2), потому что в классе std::unique_lockимеются функции-члены lock(), try_lock()и unlock(). Для выполнения реальной работы они вызывают одноименные функции контролируемого мьютекса, а сами только поднимают в экземпляре std::unique_lockфлаг, показывающий, что в данный момент этот экземпляр владеет мьютексом. Флаг необходим для того, чтобы деструктор знал, вызывать ли функцию unlock(). Если экземпляр действительно владеет мьютексом, то деструктор должен вызвать unlock(), в противном случае — не должен . Опросить состояние флага позволяет функция-член owns_lock().

Естественно, этот флаг необходимо где-то хранить. Поэтому размер объекта std::unique_lockобычно больше, чем объекта std::lock_guard, и работает std::unique_lockчуть медленнее std::lock_guard, потому что флаг нужно проверять и обновлять. Если класс std::lock_guardотвечает вашим нуждам, то я рекомендую использовать его. Тем не менее, существуют ситуации, когда std::unique_lockлучше отвечает поставленной задаче, так как без свойственной ему дополнительной гибкости не обойтись. Один из примеров — показанный выше отложенный захват; другой — необходимость передавать владение мьютексом из одного контекста в другой.

3.2.7. Передача владения мьютексом между контекстами

Поскольку экземпляры std::unique_lockне владеют ассоциированными мьютексами, то можно передавать владение от одного объекта другому путем перемещения . В некоторых случаях передача производится автоматически, например при возврате объекта из функции, а иногда это приходится делать явно, вызывая std::move(). Ситуация зависит от того, является ли источник l-значением — именованной переменной или ссылкой на нее — или r-значением — временным объектом. Если источник — r-значение, то передача владения происходит автоматически, в случае же l-значение это нужно делать явно, чтобы не получилось так, что переменная потеряет владение непреднамеренно. Класс std::unique_lockдает пример перемещаемого , но не копируемого типа. Дополнительные сведения о семантике перемещения см. в разделе А.1.1 приложения А.

Одно из возможных применений — разрешить функции захватить мьютекс, а потом передать владение им вызывающей функции, чтобы та могла выполнить дополнительные действия под защитой того же мьютекса. Ниже приведен соответствующий пример — функция get_lock()захватывает мьютекс, подготавливает некоторые данные, а потом возвращает мьютекс вызывающей программе:

std::unique_lock get_lock() {

extern std::mutex some_mutex;

std::unique_lock lk(some_mutex);

prepare_data();

return lk; ← (1)

}

void process_data() {

std::unique_lock lk(get_lock()); ← (2)

do_something();

}

Поскольку lk— автоматическая переменная, объявленная внутри функции, то ее можно возвращать непосредственно (1), не вызывая std:move(); компилятор сам позаботится о вызове перемещающего конструктора. Затем функция process_data()может передать владение своему экземпляру std::unique_lock (2), и do_something()может быть уверена, что подготовленные данные не были изменены каким-то другим потоком.

Обычно подобная схема применяется, когда подлежащий захвату мьютекс зависит от текущего состояния программы или от аргумента, переданного функции, которая возвращает объект std::unique_lock. Например, так имеет смысл делать, когда блокировка возвращается не напрямую, а является членом какого-то класса-привратника, обеспечивающего корректный доступ к разделяемым данным под защитой мьютекса. В таком случае любой доступ к данным производится через привратник, то есть предварительно необходимо получить его экземпляр (вызвав функцию, подобную get_lock()в примере выше), который захватит мьютекс. Затем для доступа к данным вызываются функции-члены объекта-привратника. По завершении операции привратник уничтожается, при этом мьютекс освобождается, открывая другим потокам доступ к защищенным данным. Такой объект-привратник вполне может быть перемещаемым (чтобы его можно было возвращать из функции), и тогда тот его член, в котором хранится блокировка, также должен быть перемещаемым.

Класс std::unique_lockтакже позволяет экземпляру освобождать блокировку без уничтожения. Для этого служит функция-член unlock(), как и в мьютексе; std::unique_lockподдерживает тот же базовый набор функций-членов для захвата и освобождения, что и мьютекс, чтобы его можно было использовать в таких обобщенных функциях, как std::lock. Наличие возможности освобождать блокировку до уничтожения объекта std::unique_lockозначает, что освобождение можно произвести досрочно в какой-то ветке кода, если ясно, что блокировка больше не понадобится. Иногда это позволяет повысить производительность приложения, ведь, удерживая блокировку дольше необходимого, вы заставляете другие потоки впустую ждать, когда они могли бы работать.

3.2.8. Выбор правильной гранулярности блокировки

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

Вот так и с потоками: если несколько потоков ждут одного ресурса (кассира), то, удерживая блокировку дольше необходимого, они заставляют другие потоки проводить в очереди больше времени (не начинайте искать баночку соуса, когда уже подошли к кассе). По возможности захватывайте мьютекс непосредственно перед доступом к разделяемым данным; старайтесь производить обработку данных, не находясь под защитой мьютекса. В частности, не начинайте длительных операций, например файловый ввод/вывод, когда удерживаете мьютекс. Ввод/вывод обычно выполняется в сотни (а то и в тысячи) раз медленнее чтения или записи того же объема данных в памяти. Поэтому если блокировка не нужна для защиты доступа к файлу, то удерживание блокировки заставляет другие потоки ждать без необходимости (так как они не могут захватить мьютекс), и тем самым вы можете свести на нет весь выигрыш от многопоточной работы.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Энтони Уильямс читать все книги автора по порядку

Энтони Уильямс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Параллельное программирование на С++ в действии. Практика разработки многопоточных программ отзывы


Отзывы читателей о книге Параллельное программирование на С++ в действии. Практика разработки многопоточных программ, автор: Энтони Уильямс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x