7
votes

Boost :: Shared_Ptr est-il sûr de l'utiliser dans plusieurs threads?

J'essayais de trouver la réponse pendant un certain temps mais j'ai échoué.

suppose que nous avons un partagé_ptr créé à partir d'un fil. Ensuite, nous transmettons ce Shared_ptr à un autre threads 2 (en utilisant une queue par exemple). Donc, à partir de ce moment, il y a 2 copies de l'original partagé_ptr , pointant sur le même pointeur brut. Les deux threads du propriétaire prendront leurs copies de ce partagé_ptr de la file d'attente. Ensuite, ils le transmettront à un autre fil ou la détruiront.

question est - est-ce sûr? Le pointeur brut sera-t-il détruit correctement (il n'y aura pas de race pour faire référence à la comptoir?) Entrez la description de l'image ici


2 commentaires

Un léger vague de votre formulation: par "Détruire", voulez-vous dire appeler réinitialiser , attribuer un nouveau pointe ou laisser le partagé_ptr sortir de la portée? Si tel est le cas, ces opérations vont bien. D'autres opérations destructives ne sont probablement pas.


Je ne planifie aucun appel de réinitialisation (). Shared_ptr sort hors de portée.


3 Réponses :


9
votes

La norme C ++ n'a presque aucune garantie concernant la sécurité du fil. Le nombre de référence de std :: partagé_ptr est la seule exception: elle est garantie de se comporter comme une variable accessible atomique. Je crois que cela est codifié dans cette phrase au § 20.7.2.2 / 4:

Modifications de user_count () ne reflètent pas les modifications pouvant introduire des courses de données.

boost :: partagé_ptr offre les mêmes garanties :

Les objets Shared_Ptr offrent le même niveau de sécurité du fil que des types intégrés. Une instance Shared_PTR peut être "LIRE" ... simultanément par plusieurs threads. Différentes instances Shared_Ptr peuvent être "écrites à" ... simultanéosly par plusieurs threads (même lorsque ces instances sont des copies et partagent le même nombre de référence en dessous.)


9 commentaires

OP est posé sur boost :: partagé_ptr cependant. Je m'attends à ce que le comportement soit le même, mais mieux être clair à ce sujet.


@ Juan Bon appel, mais le lien que vous avez fourni explicitement indique que l'opération que souhaite utiliser est en sécurité.


20.7.2.5 est également d'intérêt ici: "L'accès simultané à un objet Shared_PTR à partir de plusieurs threads n'introduit pas une course de données si l'accès est effectué exclusivement via les fonctions de cette section et l'instance est transmise comme premier argument."


@Luskan C'est ce que j'ai référencé d'abord, mais j'ai remarqué que la section ne s'applique qu'aux fonctions très spécifiques et n'est pas pertinente ici.


Pourquoi mentionnez-vous user_count () ?


@Cuciousguy C'était la seule section que je pouvais trouver qui parle en réalité d'un accès simultané à partagé_ptr , et il fait (implication) garantit que les actions de l'OP sont en sécurité. (J'avais espéré une formulation plus claire et plus directe mais pas de dés.)


Aucune garantie spécifique n'existe pour partagé_ptr . La garantie s'applique à chaque classe standard.


@Curiousguy nah. Shared_PTR est garanti d'avoir un comptage de référence atomique, de sorte que différents threads puissent copier simultanément partage_ptr des instances qui pointent sur le même objet sous-jacent. Aucune autre classe standard n'a de garanties comparables - mais aucune autre classe n'a de toute façon une sémantique comparable. Néanmoins, aucune autre description de la classe standard ne contient de libellé comparable au § 20.7.2.2 / 4, mentionnant explicitement l'accès à fil croisé sûr.


" Shared_Ptr est garanti d'avoir une référence atomique comptant " nah. Il est explicitement aucune garantie que partagé_ptr utilise même un compteur. " Aucune autre classe standard n'a de garanties comparables " NAH. Toutes les autres constructions C ++, à la fois noyau et bibliothèque, offre exactement la même garantie: La mise en œuvre ne doit pas introduire une course de données (s'il n'y en a pas dans le code source, bien sûr). " Aucune autre description de la classe standard contient le libellé comparable au §20.7.2.2 / 4, " "pas même try_lock ?



5
votes

Le Boost Docs State:

Différentes instances partagées_ptr peuvent être "écrites à" (accédées à l'aide d'opérations mutables telles que l'opérateur = ou la réinitialisation) simultanéosly par plusieurs threads ( même lorsque ces instances sont des copies et partagent le même nombre de références en dessous. )

(mettre l'accent sur le mien)

Donc, le creux ici est de savoir si vous copiez le boost :: partage_ptr s entre les threads ou non. Si vous créez des copies (le moyen «sûr» d'utiliser partagé_ptr s), vous n'avez aucune inquiétude sur la sécurité du thread-Safety. Si toutefois, vous passez le partage_ptr par référence ou par pointeur, et utilisez donc le même partagé_ptr dans différents threads, vous devez vous inquiéter de la sécurité thread-sécurité, comme décrit dans les docs.


1 commentaires

Je crée des copies et mettez-les sur la file d'attente de fil. Ensuite, la copie est extraite de la file d'attente.



0
votes

J'aimerais poster mon commentaire pour le comptage de référence dans le pointeur partagé de Boost dans les cas d'utilisation des threads multiples. Le commentaire consiste à répondre à la question qui "existe-t-il une condition de course dans le comptage de référence du pointeur partagé de Boost?"

Ma réponse simple est "non" au moins après le boost 1.35 pour la plupart des compilateurs traditionnels. La mise en oeuvre de boost appelée «add_ref_copy» définie dans le boost / détail / Shared_Count.HPP. Cette fonction invoquera la fonction atomique correspondante définie pour un compilateur individuel. Par exemple, la version Windows appellera "Boost_InterLocked_inCrementation" pour incrémenter le compte de la manière atomique (voir les détails en détail \ sp_counted_base_w32.hpp). Et le GCC Linux pour X86 appellera atomic_incrètent (...) (voir les détails en détail \ sp_counted_base_gcc_x86.hpp). Chaque compilateur individuel a mis en place le mécanisme de sécurité pour s'assurer que la mise à jour de comptage de référence de manière efficace. Certains morceaux sont même écrits en montage.

Maintenant, il y a des mises en garde dans ma réponse simple. Vous devez vraiment vous assurer que votre compilateur est inclus dans la liste bénie de Boost pour un comptage de référence multiple-sécurité. Si vous n'êtes pas sûr de pouvoir définir "BOOST_SP_USE_PTHEADADES" qui conduit boost à utiliser la bibliothèque Pthread pour effectuer une mise à jour de compte de référence atomiquement (en incluant boost / détail / sp_counted_base_pt.hpp pour la solution Pthread).


0 commentaires