У меня есть поток A, который выделяет память и назначает ее общему указателю. Затем этот поток порождает 3 других потока X, Y и Z и передает каждому копию общего указателя. Когда X, Y и Z выходят за рамки, память освобождается. Но есть ли вероятность того, что 2 потока X, Y выходят за рамки в один и тот же момент времени, и существует состояние гонки при подсчете ссылок, поэтому вместо уменьшения его на 2 он уменьшается только один раз. Итак, теперь счетчик ссылок newer падает до 0, поэтому происходит утечка памяти. Обратите внимание, что X, Y и Z только читают память. Не записывать или сбрасывать общий указатель. Короче говоря, может ли быть состояние гонки при подсчете ссылок и может ли это привести к утечке памяти?
Boost Shared Pointer: одновременный доступ для чтения в нескольких потоках
Ответы (5)
Несколько других уже предоставили ссылки на документацию, объясняющую, что это безопасно.
Чтобы получить абсолютно неопровержимое доказательство, посмотрите, как Boost Smartptr реализует свои собственные мьютексы с нуля в boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
(или соответствующем файле вашей платформы).
boost::shared_ptr
использует блокировки (или атомарный доступ без блокировок), чтобы обеспечить атомарное обновление счетчиков ссылок (даже если это неясно на странице документации). Вы можете отключить использование блокировок, если вы пишете однопоточный код, определив макрос BOOST_SP_DISABLE_THREADS
.
Обратите внимание, что примеры документации на http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm#ThreadSafety, в котором обсуждаются проблемы с множественной записью из разных потоков, обсуждает потоки, работающие с одними и теми же экземплярами shared_ptr
(объекты shared_ptr
могут быть глобальными в примеры), а не разные копии shared_ptr
, которые указывают на один и тот же объект, что является обычным вариантом использования для shared_ptr
. Пример, который вы приводите в вопросе (воздействие на копии, указывающие на общий объект), является потокобезопасным.
shared_ptr
. Лучше думать с точки зрения заблокированного монопольного доступа, чем сбой из-за того, что он оказался не в том месте и не в то время. К каким бы ресурсам ни обращались деструкторы, они должны блокироваться.
- person Potatoswatter; 02.05.2010
Нет, согласно документации, эти проблемы не могут возникнуть:
Различные экземпляры
shared_ptr
могут быть "записаны" (доступны с помощью изменяемых операций, таких как operator= или reset) одновременно несколькими потоками (даже если эти экземпляры являются копиями и имеют один и тот же счетчик ссылок внизу).
shared_ptr
, находящуюся в другом потоке, в то время как эта переменная выходит за рамки. Это было бы неопределенным (и оно также было бы неопределенным для других типов переменных, а не только для shared_ptr
). Если каждый поток получает свою собственную копию переменной shared_ptr
, эти переменные могут использоваться (и выходить за рамки) независимо, даже если они указывают на один и тот же объект (как в примере 2 в документации).
- person sth; 22.04.2010
В документации говорится:
Различные экземпляры shared_ptr могут быть «записаны» (доступны с помощью изменяемых операций, таких как operator= или reset) одновременно несколькими потоками (даже если эти экземпляры являются копиями и имеют один и тот же счетчик ссылок внизу).
Поэтому, если ни один из потоков не обращается к объектам-указателям других потоков, все должно быть в порядке. Пожалуйста, ознакомьтесь с примерами в документации и определите, какой из них подходит для вашего случая.
Лучше всего было бы перейти на TR1 или C++0x shared_ptr, а не на версию Boost. Я считаю, что стандартизировано, что они ДОЛЖНЫ быть потокобезопасными.