Контейнеры и потоки STL (одновременная запись) в Linux

#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, а не управлять ресурсом синхронизации (разблокировка мьютекса и т. Д.) Вручную.

Вы можете обратиться к документации здесь:

MSDN:

Если один объект записывается одним потоком, то все операции чтения и записи в этот объект в том же или других потоках должны быть защищены. Например, для данного объекта 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. Я обновлю свой вопрос