Повышение общего указателя: одновременный доступ для чтения в нескольких потоках - PullRequest
6 голосов
/ 22 апреля 2010

У меня есть поток A, который выделяет память и назначает ее для общего указателя. Затем этот поток порождает 3 других потока X, Y и Z и передает копию общего указателя каждому. Когда X, Y и Z выходят из области видимости, память освобождается. Но есть ли вероятность того, что 2 потока X, Y выходят из области действия в один и тот же момент времени, и при подсчете ссылок возникает условие гонки, поэтому вместо уменьшения на 2 он уменьшается только один раз. Итак, теперь счетчик ссылок новее падает до 0, поэтому происходит утечка памяти. Обратите внимание, что X, Y и Z читают только память. Не запись или сброс общего указателя. Короче говоря, может ли быть состояние гонки на счетчике ссылок и это может привести к утечкам памяти?

Ответы [ 5 ]

12 голосов
/ 22 апреля 2010

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 s.Пример, который вы даете в вопросе (действует на копии, указывающие на общий объект), является поточно-ориентированным.

6 голосов
/ 22 апреля 2010

Нет, согласно документации , эти проблемы не могут возникнуть:

Различные shared_ptr экземпляры могут быть "записаны" (доступ к ним осуществляется с помощью изменяемых операций, таких как operator = или reset) одновременно несколькими потоками (, даже если эти экземпляры являются копиями, и совместно используют один и тот же счетчик ссылок под .)

2 голосов
/ 26 апреля 2010

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

Для абсолютно неопровержимых доказательств посмотрите, как Boost Smartptr фактически реализует свои собственные мьютексы с нуля в boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp (или соответствующий файл вашей платформы).

1 голос
/ 22 апреля 2010

Документация гласит:

Различные экземпляры shared_ptr могут быть «записаны» (доступ к ним осуществляется с помощью изменяемых операций, таких как operator = или reset) одновременно несколькими потоками (даже если эти экземпляры являются копиями и имеют общий счетчик ссылок под ними.)

Так что, если ни один из потоков не обращается к объектам-указателям других потоков, все должно быть в порядке. Пожалуйста, посмотрите на примеры в документации и посмотрите, какой из них подходит для вашего случая.

0 голосов
/ 02 мая 2010

Лучше всего сделать обновление до TR1 или C ++ 0x shared_ptr, в отличие от варианта Boost. Я считаю, что стандартизировано, что они ДОЛЖНЫ быть поточно-ориентированными.

...