Czytam http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.html i niektóre problemy z bezpieczeństwem wątków nadal nie są dla mnie jasne:
- Standardowo gwarantuje, że zliczanie referencji jest obsługiwane wątkowo i niezależne od platformy, prawda?
- Podobny problem - standardowa gwarancja, że tylko jeden wątek (trzymający ostatnią referencję) wywoła delete na udostępnionym obiekcie, prawda?
- shared_ptr nie gwarantuje żadnego bezpieczeństwa wątków dla przechowywanych w nim obiektów?
EDYTOWAĆ:
Pseudo kod:
// 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));
Wywołanie reset () w wątku IV spowoduje usunięcie poprzedniej instancji klasy A utworzonej w pierwszym wątku i zastąpienie jej nową instancją? Ponadto po wywołaniu reset () w wątku IV inne wątki będą widzieć tylko nowo utworzony obiekt?
c++
c++11
shared-ptr
Głupkowaty
źródło
źródło
make_shared
zamiastnew
Odpowiedzi:
Jak zauważyli inni, udało Ci się poprawnie zorientować się w trzech pierwotnych pytaniach.
Ale ostatnia część twojej edycji
jest nieprawidłowe. Tylko
d
będzie wskazywać na nowyA(10)
, ia
,b
ic
nadal będzie punkt do oryginałuA(1)
. Widać to wyraźnie na poniższym krótkim przykładzie.(Najwyraźniej nie zawracałem sobie głowy wątkami: to nie ma wpływu na
shared_ptr::reset()
zachowanie.)Dane wyjściowe tego kodu to
źródło
Prawidłowo,
shared_ptr
używaj atomowych przyrostów / ubytków wartości zliczania odniesienia.Standard gwarantuje, że tylko jeden wątek wywoła operator usuwania na udostępnionym obiekcie. Nie jestem pewien, czy konkretnie określa, że ostatnim wątkiem, który usuwa swoją kopię współdzielonego wskaźnika, będzie ten, który wywołuje usuwanie (prawdopodobnie w praktyce tak będzie).
Nie, przechowywany w nim obiekt może być jednocześnie edytowany przez wiele wątków.
EDYCJA: Drobne uzupełnienie, jeśli chcesz dowiedzieć się, jak ogólnie działają wskaźniki współdzielone, możesz zajrzeć do
boost::shared_ptr
źródła: http://www.boost.org/doc/libs/1_37_0/boost/shared_ptr.hpp .źródło
std::shared_ptr
nie jest bezpieczny dla wątków.Współdzielony wskaźnik to para dwóch wskaźników, jeden do obiektu, a drugi do bloku kontrolnego (trzymanie licznika ref, linki do słabych wskaźników ...).
Może istnieć wiele std :: shared_ptr i za każdym razem, gdy uzyskują dostęp do bloku kontrolnego w celu zmiany licznika odniesienia, jest to bezpieczne wątkowo, ale
std::shared_ptr
samo w sobie NIE jest bezpieczne dla wątków ani niepodzielne.Jeśli przypiszesz nowy obiekt do
std::shared_ptr
chwili, gdy inny wątek go używa, może skończyć się z nowym wskaźnikiem obiektu, ale nadal będzie używać wskaźnika do bloku kontrolnego starego obiektu => CRASH.źródło
std::shared_ptr
instancja nie jest bezpieczna dla wątków. Z referencji 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>
jest zawsze używane jako bezpieczne wątkowo przez wartość (kopiowaną / przenoszoną) poza granice wątku. Wszystkie inne zastosowaniastd::shared_ptr<T>&
są niebezpieczne poza granicami wątków