Ich lese http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.html und einige Probleme mit der Thread-Sicherheit sind mir immer noch nicht klar:
- Standard garantiert, dass die Referenzzählung threadsicher und plattformunabhängig ist, oder?
- Ähnliches Problem - Standard garantiert, dass nur ein Thread (der die letzte Referenz enthält) delete für ein freigegebenes Objekt aufruft, oder?
- shared_ptr garantiert keine Thread-Sicherheit für darin gespeicherte Objekte?
BEARBEITEN:
Pseudocode:
// 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));
Durch Aufrufen von reset () in Thread IV wird die vorherige Instanz einer im ersten Thread erstellten Klasse gelöscht und durch eine neue Instanz ersetzt. Darüber hinaus sehen andere Threads nach dem Aufruf von reset () im IV-Thread nur neu erstellte Objekte?
c++
c++11
shared-ptr
Doof
quelle
quelle
make_shared
anstelle vonnew
Antworten:
Wie andere bereits betont haben, haben Sie es in Bezug auf Ihre ursprünglichen 3 Fragen richtig herausgefunden.
Aber der letzte Teil Ihrer Bearbeitung
ist falsch. Nur
d
zeigt auf das neueA(10)
, unda
,b
undc
zeigt weiterhin auf das OriginalA(1)
. Dies ist im folgenden kurzen Beispiel deutlich zu sehen.(Klar, ich habe mich nicht um Threading gekümmert: das berücksichtigt das
shared_ptr::reset()
Verhalten nicht.)Die Ausgabe dieses Codes ist
quelle
Richtig,
shared_ptr
s verwenden atomare Inkremente / Dekremente eines Referenzzählwerts.Der Standard garantiert, dass nur ein Thread den Löschoperator für ein freigegebenes Objekt aufruft. Ich bin nicht sicher, ob es speziell angibt, dass der letzte Thread, der seine Kopie des gemeinsam genutzten Zeigers löscht, derjenige ist, der delete aufruft (in der Praxis wäre dies wahrscheinlich der Fall).
Nein, das darin gespeicherte Objekt kann von mehreren Threads gleichzeitig bearbeitet werden.
BEARBEITEN: Leichtes Follow-up. Wenn Sie sich ein Bild davon machen möchten, wie freigegebene Zeiger im Allgemeinen funktionieren, sollten Sie sich die
boost::shared_ptr
Quelle ansehen : http://www.boost.org/doc/libs/1_37_0/boost/shared_ptr.hpp .quelle
std::shared_ptr
ist nicht threadsicher.Ein gemeinsam genutzter Zeiger ist ein Paar von zwei Zeigern, einer auf das Objekt und einer auf einen Steuerblock (hält den Referenzzähler, verknüpft mit schwachen Zeigern ...).
Es kann mehrere std :: shared_ptr geben, und wenn sie auf den Steuerblock zugreifen, um den Referenzzähler zu ändern, ist er threadsicher, aber der
std::shared_ptr
selbst ist NICHT threadsicher oder atomar.Wenn Sie ein neues Objekt einer
std::shared_ptr
Zeit zuweisen, in der ein anderer Thread es verwendet, wird möglicherweise der neue Objektzeiger angezeigt, es wird jedoch weiterhin ein Zeiger auf den Steuerblock des alten Objekts verwendet => CRASH.quelle
std::shared_ptr
Instanz nicht threadsicher ist. Von std :: shared_ptr Referenz: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>
Instanz ist garantiert threadsicher, wenn sie immer von einem Wert (kopiert / verschoben) über Threadgrenzen hinweg verwendet wird. Alle anderen Verwendungenstd::shared_ptr<T>&
sind über Thread-Grenzen hinweg unsicher