#c #linux #stl #concurrency #pthreads
#c #linux #stl #параллелизм #p — потоки
Вопрос:
Я ищу оптимальную стратегию для использования контейнеров STL (например, std::map и std::vector) и pthreads.
Каков канонический путь? Простой пример:
std::map<string, vector<string>> myMap;
Как мы можем гарантировать параллелизм?
mutex_lock;
write at myMap;
mutex_unlock;
Кроме того, я хотел бы знать, сталкиваются ли pthreads и STL с проблемами производительности при совместном использовании.
Система: Liunx, g , pthreads, нет boost, нет Intel TBB
Ответ №1:
Стандарт C 03 вообще не говорит о параллелизме, поэтому аспект параллелизма не учитывается как деталь реализации для компиляторов. Итак, в документации, прилагаемой к вашему компилятору, следует искать ответы, связанные с параллелизмом.
Большинство реализаций STL не являются потокобезопасными как таковые.
Поскольку контейнеры STL не обеспечивают какой-либо явной потокобезопасности, так что да, вам придется использовать свой собственный механизм синхронизации. И пока вы этим занимаетесь, вам следует использовать RAII, а не управлять ресурсом синхронизации (разблокировка мьютекса и т. Д.) Вручную.
Вы можете обратиться к документации здесь:
Если один объект записывается одним потоком, то все операции чтения и записи в этот объект в том же или других потоках должны быть защищены. Например, для данного объекта A, если поток 1 выполняет запись в A, то потоку 2 должно быть запрещено чтение или запись в A.
В документации GCC говорится:
в настоящее время мы используем определение безопасности потоков SGI STL, в котором говорится:
SGI-реализация STL является потокобезопасной только в том смысле, что одновременный доступ к отдельным контейнерам безопасен, а одновременный доступ на чтение к общим контейнерам безопасен. Если несколько потоков обращаются к одному контейнеру, и по крайней мере один поток потенциально может выполнять запись, то пользователь несет ответственность за обеспечение взаимного исключения между потоками во время доступа к контейнеру.
Обратите внимание: стандартная библиотека GCC является производной от STL-кода SGI.
Комментарии:
1. RAII — хорошая идея, однако применяется ли это, когда я возвращаю элемент в свой вектор?
2. @cateof: Да, если какой-то другой поток считывает данные из вашего вектора во время вызова
push_back
, то это проблема. Так что да, это применимо.
Ответ №2:
Канонический способ обеспечения параллелизма — удерживать блокировку при доступе к коллекции.
Это работает в 90% случаев, когда доступ к коллекции в любом случае не критичен для производительности. Если вы обращаетесь к общей коллекции настолько часто, что блокировка вокруг нее снижает производительность, вам следует пересмотреть свой дизайн. (И скорее всего, ваш дизайн в порядке, и это не повлияет на производительность почти так сильно, как вы могли бы подозревать.)
Ответ №3:
Вам следует взглянуть на блоки построения потоков Intel tbb ( http://threadingbuildingblocks.org / ). У них есть несколько очень оптимизированных структур данных, которые обрабатывают параллелизм внутри, используя неблокирующие стратегии.
Комментарии:
1. @Micheal, я виноват. Мы не можем использовать concurrent_vector из TBB. Я обновлю свой вопрос