Я читаю http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.html, и мне все еще не понятны некоторые проблемы с безопасностью потоков:
- Стандарт гарантирует, что подсчет ссылок является потокобезопасным и независимым от платформы, верно?
- Аналогичная проблема - стандартные гарантии, что только один поток (содержащий последнюю ссылку) вызовет удаление для общего объекта, верно?
- shared_ptr не гарантирует безопасность потоков для объекта, хранящегося в нем?
РЕДАКТИРОВАТЬ:
Псевдокод:
// Thread I
shared_ptr<A> a (new A (1));
// Thread II
shared_ptr<A> b (a);
// Thread III
shared_ptr<A> c (a);
// Thread IV
shared_ptr<A> d (a);
d.reset (new A (10));
Вызов reset () в потоке IV удалит предыдущий экземпляр класса A, созданный в первом потоке, и заменит его новым экземпляром? Более того, после вызова reset () в потоке IV другие потоки будут видеть только вновь созданный объект?
c++
c++11
shared-ptr
Тупой
источник
источник
make_shared
вместоnew
Ответы:
Как отмечали другие, вы правильно поняли свои исходные 3 вопроса.
Но заключительная часть вашего редактирования
это неверно. Только
d
будет указывать на новыйA(10)
, иa
,b
иc
будет по- прежнему точки к оригиналуA(1)
. Это хорошо видно на следующем коротком примере.(Ясно, что я не стал беспокоиться о потоковой передаче: это не влияет на
shared_ptr::reset()
поведение.)Результатом этого кода является
источник
Правильно,
shared_ptr
используйте атомарные приращения / уменьшения значения счетчика ссылок.Стандарт гарантирует, что только один поток вызовет оператор удаления для общего объекта. Я не уверен, что он специально указывает, что последний поток, который удаляет свою копию общего указателя, будет тем, который вызывает удаление (вероятно, на практике так и будет).
Нет, хранящийся в нем объект может одновременно редактироваться несколькими потоками.
РЕДАКТИРОВАТЬ: небольшое продолжение, если вы хотите понять, как общие указатели работают в целом, вы можете посмотреть
boost::shared_ptr
источник: http://www.boost.org/doc/libs/1_37_0/boost/shared_ptr.hpp .источник
std::shared_ptr
не является потокобезопасным.Общий указатель - это пара из двух указателей, один на объект, а другой на блок управления (содержащий счетчик ссылок, ссылки на слабые указатели ...).
Может быть несколько std :: shared_ptr, и всякий раз, когда они обращаются к блоку управления для изменения счетчика ссылок, он является потокобезопасным, но
std::shared_ptr
сам НЕ является потокобезопасным или атомарным.Если вы назначаете новый объект,
std::shared_ptr
пока другой поток использует его, он может получить указатель на новый объект, но все еще будет использовать указатель на блок управления старого объекта => CRASH.источник
std::shared_ptr
экземпляр не является потокобезопасным. Из ссылки std :: shared_ptr:If multiple threads of execution access the same shared_ptr without synchronization and any of those accesses uses a non-const member function of shared_ptr then a data race will occur;
std::shared_ptr<T>
Экземпляр гарантируется поточно-когда всегда по значению (копируется / перемещается) через границу резьбы. Любое другое использованиеstd::shared_ptr<T>&
небезопасно