У меня есть поток A, который выделяет память и назначает ее совместно используемому указателю. Затем этот поток генерирует 3 других потока X, Y и Z и передает копию общего указателя на каждый. Когда X, Y и Z выходят за рамки, память освобождается. Но есть ли вероятность того, что 2 потока X, Y выйдут из области видимости в тот же момент времени, и есть условие гонки на счетчике ссылок, вместо того, чтобы декрементировать его на 2, он только уменьшается один раз. Итак, теперь счетчик ссылок уменьшается до 0, поэтому происходит утечка памяти. Обратите внимание, что X, Y и Z считывают только память. Не записывать и не восстанавливать общий указатель. Короче говоря, может быть состояние гонки на счетчике ссылок и может ли это привести к утечкам памяти?Boost Shared Pointer: одновременный доступ для чтения через несколько потоков
ответ
Некоторые другие уже предоставили ссылки на документацию, поясняющую, что это безопасно.
Для абсолютно неопровержимого доказательства см., Как Boost Smartptr фактически реализует свои собственные мьютексы с нуля в boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
(или соответствующий файл вашей платформы).
Нет, в соответствии с the documentation, эти проблемы не могут возникнуть:
Различных
shared_ptr
экземпляры могут быть «записаны» (доступ с помощью изменяемых операций, таких как оператор = или сбросить) simultaneosly нескольких потоков (, даже если эти экземпляры являются копиями, а одни и те же счетчик ссылок внизу.)
У меня есть вопрос: согласитесь с документацией, смешанная ситуация может привести к неопределенным beahvior: (...) // --- Пример 4 --- // нить A p3 = p2; // читает p2, p3 пишет // поток B // p2 выходит из области видимости не определено, деструктор считается «доступ на запись» (...) не мы в этой ситуации здесь? – Grimmy
Пример ниже показывает поведение как «неопределенное», когда оно выходит за рамки. –
@Grimmy, @Brian: В моем понимании в примере 4 в документации один поток пытается прочитать переменную 'shared_ptr', живущую в другом потоке, в то время как эта переменная выходит за рамки. Это будет неопределенным (и оно также будет неопределенным для других типов переменных, а не только для 'shared_ptr'). Если каждый поток получает свою собственную копию переменной shared_ptr, эти переменные могут использоваться (и выходить за рамки) независимо, даже если они указывают на один и тот же объект (как в примере 2 в документации). – sth
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
. Пример, который вы задаете в вопросе (действующий на копии, указывающие на общий объект), является потокобезопасным.
Комментарий точно правильный, но я бы также добавил, что вызов деструктора некоторых объектов из «неправильного» потока или «неправильного» времени может создавать обычные виды многопоточных ошибок, таких как расы и тупики. Если уничтоженный объект освобождает память, это не должно быть проблемой. Однако деструкторы, которые делают такие вещи, как дезактивация обреченного объекта другими компонентами системы, могут определенно вызвать проблемы. – Doug
@Doug, который не имеет ничего общего с 'shared_ptr'. Лучше думать с точки зрения заблокированного эксклюзивного доступа, чем «он разбился, потому что он был не в том месте в неподходящее время». Какими бы ни были ресурсы, доступ к деструкторам должен блокироваться. – Potatoswatter
@Potatoswatter: Да, я понимаю, что проблема, которую я поднял, напрямую не связана с безопасностью потока shared_ptr. Я не думаю о гоночных условиях, поскольку «это было не в то место в неподходящее время». Я нашел ошибки, вызванные shared_ptrs, которые потеряли свою последнюю ссылку (скажем) на не основной поток и где деструктор выполняет нетривиальную очистку. Это точно так же, как удаление указателя вручную, хотя - «такая же безопасность потока, как и исходные указатели», как указано в документации. – Doug
documentation говорит:
Различные экземпляры shared_ptr могут быть «записаны» (доступ с помощью изменяемом операций, таких как оператор = или сбросить) simultaneosly несколькими потоками (даже если эти экземпляры являются копиями, а доля тот же номер ссылки внизу.)
Так что, если ни одна из нитей не обращается к объектам указателя других потоков, это должно быть хорошо. Пожалуйста, ознакомьтесь с примерами в документации и посмотрите, какая из них имеет отношение к вашему делу.
Лучше всего было бы перейти на TR1 или C++ 0x shared_ptr, в отличие от разнообразия Boost. Я считаю, что стандартизировано, что они ДОЛЖНЫ быть потокобезопасными.
- 1. Boost Shared Pointer array
- 2. Запустить несколько потоков Одновременный
- 3. using boost shared pointer в std :: string для назначения переменной
- 4. Одновременный доступ нескольких потоков и глобальный мьютекс
- 5. ReentrantReadWriteLock несколько потоков для чтения
- 6. highcharts shared tooltips pointer
- 7. C++ fstream одновременный доступ
- 8. Доступ к файлу через несколько потоков
- 9. Пример для boost shared_mutex (несколько операций чтения/записи)?
- 10. Boost Asio, Несколько потоков и несколько io_service
- 11. доступ для чтения из нескольких потоков
- 12. Доступ к файлам для чтения из потоков
- 13. Несколько потоков чтения случайных файлов
- 14. Unmapping boost shared memory
- 15. Move Конструктор и оператор = для Shared Pointer
- 16. POCO: одновременный доступ к SecureStreamSocket
- 17. Boost interprocess_condition несколько потоков, вызывающих wait() fail
- 18. Нужно ли блокировать одновременный доступ SQLite для операторов SELECT?
- 19. MySQL: одновременный доступ
- 20. Одновременный доступ к файлам
- 21. Несколько потоков чтения из того же файла
- 22. QWizard: QWizardPage :: registerField vs shared object pointer
- 23. Boost Scoped Pointer To Boost Thread
- 24. Умножает одновременный доступ к одному потоку
- 25. nservicebus одновременный доступ к данным саги
- 26. предотвращает одновременный запуск метода из разных потоков
- 27. boost :: shared_mutex vs boost :: mutex для написания нескольких потоков?
- 28. Boost Memory Mapped File: доступ для чтения-записи
- 29. Управление сеансом через несколько потоков/узлы
- 30. JUnit одновременный доступ к synchronizedSet
Интересно, что два человека использовали одну и ту же документацию для достижения противоположных выводов. –
@Mark: Я бы сказал, что документы не совсем кристально чисты (не сказать, что они ошибаются, просто они легко ошибочно интерпретируются). –
Я не понимаю, почему у вас есть щедрость на ваш вопрос.Ответ уже есть :) –