stl map найти нить безопасно - PullRequest
12 голосов
/ 06 мая 2011

Безопасен ли поиск вызовов на карте STL?

Ответы [ 4 ]

13 голосов
/ 06 мая 2011

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

При этом разные реализации, похоже, предлагают разные гарантии.Например, большинство из них допускают одновременное использование нескольких читателей, если запись не выполняется одновременно.Если вас не волнует переносимость, вы можете изучить документацию для вашей реализации.Например, из здесь для SGI STL:

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

С этот ответ , похоже, Dinkumware дает аналогичную гарантию (они являются реализацией Microsoft STL).

Несколько потоков могут безопасно считывать один и тот же контейнерный объект.(В объекте контейнера есть незащищенные изменяемые подобъекты.)

Два потока могут безопасно манипулировать различными объектами контейнера одного и того же типа.(В типе контейнера нет незащищенных общих статических объектов.)

Необходимо защитить от одновременного доступа к объекту контейнера, если хотя бы один поток изменяет объект.(Очевидные примитивы синхронизации, такие как в библиотеке потоков Dinkum, не будут уничтожены объектом-контейнером.)

3 голосов
/ 04 августа 2015

Я пытался найти ответ на вопрос.

https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-3.4/stl__map_8h-source.html

Вы можете увидеть карту STL Souce.


поиск find(). Он находится в 497 строке, 524 линии. Код записывается как _M_t.find(__x);


Затем поиск _M_t.

Найдено в 124 строке. Это записано как _Rep_type _M_t;


Если для потока создается свойство _M_t, оно может быть поточно-ориентированным. Но я так не думаю. Если 2 потока используют find одновременно, они будут использовать _M_t одновременно. _Rep_type подключен к _Rb_tree.

Вы можете увидеть _Rb_tree в источнике ниже.

https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.1/stl__tree_8h-source.html

find() сделать путешествие по дереву (см. Код ниже). произойдет нежелательное изменение __x и __y.

01307   template<typename _Key, typename _Val, typename _KeyOfValue,
01308            typename _Compare, typename _Alloc>
01309     typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator
01310     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
01311     find(const _Key& __k)
01312     {
01313       _Link_type __x = _M_begin(); // Current node.
01314       _Link_type __y = _M_end(); // Last node which is not less than __k.
01315 
01316       while (__x != 0)
01317     if (!_M_impl._M_key_compare(_S_key(__x), __k))
01318       __y = __x, __x = _S_left(__x);
01319     else
01320       __x = _S_right(__x);
01321 
01322       iterator __j = iterator(__y);
01323       return (__j == end()
01324           || _M_impl._M_key_compare(__k,
01325                     _S_key(__j._M_node))) ? end() : __j;
01326     }
3 голосов
/ 06 мая 2011

Нет: когда другой поток обновляет карту одновременно с вашим find, поведение не определено.

0 голосов
/ 08 мая 2013

На самом деле, STL, поставляемый с Microsoft Visual Studio 2008, кажется, имеет некоторые блокировки операций, которые изменяют карту (и я предполагаю, что это то же самое для набора).Это довольно раздражает, так как я строю больше карт в нескольких потоках, и это убивает мою производительность.

...