Потокобезопасные Контейнеры

Всем Привет

Я тут читаю «Параллельное программирование в действии» и там автор указывает что встроенный, например стэк не подходит для многопоточных программ из-за Гонки Данных. Поэтому он создал для него обертку, которая обеспечивает безопасность данных.

Получается если я хочу юзать тот или иной контейнер мне нужно его переделать под Thread Safe?


Ответы (2 шт):

Автор решения: Komdosh

Да, чаще всего стандартные реализации не рассчитаны на использование в параллельной среде.

Многопоточность приносит очень много проблем с потокобезопасностью. Критические секции, мьютексы и прочие механизмы синхронизации сказываются на времени выполнении программ, так как появляется дополнительный код, который также расходует процессорное время.

Стоит ли писать данный код самому? - для самообразования стоит, в иных случаях лучше воспользоваться готовыми вариантами. Имеется огромное количество библиотек с такими структурами и алгоритмами.

→ Ссылка
Автор решения: Alex Guteniev

Чаще всего многопоточные контейнеры вообще не используются. Вместо них используются обычные, с ними либо работают только в одном потоке, либо используют внешнюю по отношению к контейнеру синхронизацию.

Контейнеры со встроенным мьютексом бывают, но не применяются широко, т.к. они неэффективны и ограниченны.

Использование внешней по отношению к контейнеру блокировки даёт то преимущество, что можно поместить несколько операций под одну блокировку. Это и обеспечивает корректность многих сценариев, и более эффективно. Например:

std::vector<int> v;
v.erase(std::remove_if(v.begin(), v.end(), pred), v.end());

поддержку такого использования не получится обеспечить внутренним мьютексом, т.к. контейнер может меняться между вызовами его методов. И если бы можно было, то захват мьютекса был бы на каждую операцию, что дорого.

Бывают контейнеры, которые не требуют блокировки, и не используют внутренних мьютексов (lock-free). Их использовать больше смысла, но они не получаются из обычных путём доработки, они заранее разрабатываются с учётом многопоточности. В Boost есть Boost.Lockfree, например.

→ Ссылка