Потокобезопасные Контейнеры
Всем Привет
Я тут читаю «Параллельное программирование в действии» и там автор указывает что встроенный, например стэк не подходит для многопоточных программ из-за Гонки Данных. Поэтому он создал для него обертку, которая обеспечивает безопасность данных.
Получается если я хочу юзать тот или иной контейнер мне нужно его переделать под Thread Safe?
Ответы (2 шт):
Да, чаще всего стандартные реализации не рассчитаны на использование в параллельной среде.
Многопоточность приносит очень много проблем с потокобезопасностью. Критические секции, мьютексы и прочие механизмы синхронизации сказываются на времени выполнении программ, так как появляется дополнительный код, который также расходует процессорное время.
Стоит ли писать данный код самому? - для самообразования стоит, в иных случаях лучше воспользоваться готовыми вариантами. Имеется огромное количество библиотек с такими структурами и алгоритмами.
Чаще всего многопоточные контейнеры вообще не используются. Вместо них используются обычные, с ними либо работают только в одном потоке, либо используют внешнюю по отношению к контейнеру синхронизацию.
Контейнеры со встроенным мьютексом бывают, но не применяются широко, т.к. они неэффективны и ограниченны.
Использование внешней по отношению к контейнеру блокировки даёт то преимущество, что можно поместить несколько операций под одну блокировку. Это и обеспечивает корректность многих сценариев, и более эффективно. Например:
std::vector<int> v;
v.erase(std::remove_if(v.begin(), v.end(), pred), v.end());
поддержку такого использования не получится обеспечить внутренним мьютексом, т.к. контейнер может меняться между вызовами его методов. И если бы можно было, то захват мьютекса был бы на каждую операцию, что дорого.
Бывают контейнеры, которые не требуют блокировки, и не используют внутренних мьютексов (lock-free). Их использовать больше смысла, но они не получаются из обычных путём доработки, они заранее разрабатываются с учётом многопоточности. В Boost есть Boost.Lockfree, например.