Je lis http://gcc.gnu.org/onlinedocs/libstdc++/manual/shared_ptr.html et certains problèmes de sécurité du fil ne sont toujours pas clairs pour moi:
MODIFIER:
Pseudo code:
// 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));
L'appel de reset () dans le thread IV supprimera l'instance précédente d'une classe créée dans le premier thread et la remplacera par une nouvelle instance? De plus, après avoir appelé reset () dans le thread IV, les autres threads ne verront que le nouvel objet créé?
Comme d’autres l’ont fait remarquer, vous avez bien compris le contenu de vos 3 questions initiales.
Mais la fin de votre montage
L'appel de reset () dans le thread IV supprimera l'instance précédente d'une classe créée dans le premier thread et la remplacera par une nouvelle instance? De plus, après avoir appelé reset () dans le thread IV, les autres threads ne verront que le nouvel objet créé?
est incorrect. Seul d
pointe vers le nouveau A(10)
, et a
, b
et c
continuera de pointer vers le premier A(1)
. Cela se voit clairement dans le court exemple suivant.
#include <memory>
#include <iostream>
using namespace std;
struct A
{
int a;
A(int a) : a(a) {}
};
int main(int argc, char **argv)
{
shared_ptr<A> a(new A(1));
shared_ptr<A> b(a), c(a), d(a);
cout << "a: " << a->a << "\tb: " << b->a
<< "\tc: " << c->a << "\td: " << d->a << endl;
d.reset(new A(10));
cout << "a: " << a->a << "\tb: " << b->a
<< "\tc: " << c->a << "\td: " << d->a << endl;
return 0;
}
(Clairement, je ne me suis pas soucié de tout thread: cela ne prend pas en compte le comportement shared_ptr::reset()
.)
La sortie de ce code est
a: 1 b: 1 c: 1 d: 1
a: 1 b: 1 c: 1 d: 10
Correct, shared_ptr
s utilise des incréments/décréments atomiques d'une valeur de comptage de référence.
La norme garantit qu'un seul thread appellera l'opérateur de suppression sur un objet partagé. Je ne sais pas s'il spécifie spécifiquement que le dernier thread qui supprime sa copie du pointeur partagé sera celui qui appelle delete (ce qui est probablement le cas dans la pratique).
Non, l'objet qui y est stocké peut être édité simultanément par plusieurs threads.
EDIT: Léger suivi, si vous voulez avoir une idée du fonctionnement des pointeurs partagés en général, vous voudrez peut-être regarder le boost::shared_ptr
source: http://www.boost.org/doc/libs/1_37_0/boost/shared_ptr.hpp .
std::shared_ptr
n'est pas thread-safe.
Un pointeur partagé est une paire de deux pointeurs, l'un sur l'objet et l'autre sur un bloc de contrôle (tenant le compteur de références, des liens vers des pointeurs faibles, etc.).
Il peut y avoir plusieurs std :: shared_ptr et chaque fois qu'ils accèdent au bloc de contrôle pour changer le compteur de références, il est thread-safe mais le std::shared_ptr
lui-même n'est ni thread-safe ni atomique.
Si vous affectez un nouvel objet à un std::shared_ptr
alors qu’un autre thread l’utilise, il peut se retrouver avec le nouveau pointeur d’objet mais en utilisant tout de même un pointeur sur le bloc de contrôle de l’objet ancien => CRASH.