web-dev-qa-db-fra.com

Std :: vector ou boost :: vector thread est-il sûr?

J'ai plusieurs threads appelant simultanément Push_back() sur un objet partagé de std::vector. Est std::vector fil sûr? Ou dois-je implémenter le mécanisme moi-même pour le rendre sûr pour les threads?
Je veux éviter de faire des travaux supplémentaires "verrouillage et libération" parce que je suis un utilisateur de bibliothèque plutôt qu'un concepteur de bibliothèque. J'espère rechercher des solutions thread-safe existantes pour le vecteur. Que diriez-vous boost::vector, nouvellement introduit à partir de boost 1.48. en avant. Est-il sûr pour les threads?

35
Jacky Lee

Le standard C++ offre certaines garanties de thread pour toutes les classes de la bibliothèque C++ standard. Ces garanties peuvent ne pas être ce que vous attendez qu'elles soient, mais pour toutes les classes de bibliothèque C++ standard, certaines garanties de sécurité des threads sont faites. Assurez-vous de lire les garanties apportées, car les garanties de threading des conteneurs C++ standard ne s'alignent généralement pas sur ce que vous souhaitez qu'elles soient. Pour certaines classes, des garanties différentes, généralement plus fortes, sont faites et la réponse ci-dessous s'applique spécifiquement aux conteneurs. Les conteneurs ont essentiellement les garanties de sécurité de filetage suivantes:

  1. il peut y avoir plusieurs lecteurs simultanés du même conteneur
  2. s'il n'y a qu'un écrivain, il n'y aura plus d'écrivains et plus de lecteurs

Ce ne sont généralement pas ce que les gens voudraient comme garanties de sécurité des threads, mais ils sont très raisonnables compte tenu de l'interface des conteneurs standard: ils sont destinés à être utilisés efficacement en l'absence de threads d'accès multiples. L'ajout de tout type de verrouillage pour leurs méthodes interférerait avec cela. Au-delà de cela, l'interface des conteneurs n'est vraiment utile pour aucune forme de verrouillage interne: généralement plusieurs méthodes sont utilisées et les accès dépendent du résultat des accès précédents. Par exemple, après avoir vérifié qu'un conteneur n'est pas empty() un élément peut être accédé. Cependant, avec le verrouillage interne, rien ne garantit que l'objet se trouve toujours dans le conteneur lors de son accès réel.

Pour répondre aux exigences qui donnent les garanties ci-dessus, vous devrez probablement utiliser une certaine forme de verrouillage externe pour les conteneurs accédés simultanément. Je ne connais pas les conteneurs boost mais s'ils ont une interface similaire à celle des conteneurs standard, je soupçonne qu'ils ont exactement les mêmes garanties.

Les garanties et les exigences sont données au paragraphe 1 du 17.6.4.10 [res.on.objects]:

Le comportement d'un programme n'est pas défini si les appels aux fonctions de bibliothèque standard à partir de différents threads peuvent introduire une course aux données. Les conditions dans lesquelles cela peut se produire sont spécifiées au 17.6.5.9. [Remarque: la modification d'un objet d'un type de bibliothèque standard partagé entre des threads risque un comportement indéfini sauf si les objets de ce type sont explicitement spécifiés comme partageables sans courses de données ou si l'utilisateur fournit un mécanisme de verrouillage. —Note]

... et 17.6.5.9 [res.on.data.races]. Cette section détaille essentiellement la description la plus informelle du not.

54
Dietmar Kühl

J'ai plusieurs threads appelant simultanément Push_back () sur un objet partagé de std :: vector. Le thread std :: vector est-il sûr?

C'est dangereux.

Ou dois-je implémenter le mécanisme moi-même pour le rendre sûr pour les threads?

Oui.

Je veux éviter de faire des travaux supplémentaires de "verrouillage et de libération" parce que je suis un utilisateur de bibliothèque plutôt qu'un concepteur de bibliothèque. J'espère rechercher des solutions thread-safe existantes pour le vecteur.

Eh bien, l'interface de vector n'est pas optimale pour une utilisation simultanée. C'est bien si le client a accès à un verrou, mais pour que l'interface fasse un résumé du verrouillage pour chaque opération - non. En fait, l'interface de vector ne peut garantir la sécurité des threads sans verrouillage externe (en supposant que vous ayez besoin d'opérations qui mutent également).

Que diriez-vous de boost :: vector, qui a été récemment introduit à partir du boost 1.48.0. Est-il sûr pour les threads?

Les documents indiquent:

//! boost::container::vector is similar to std::vector but it's compatible
//! with shared memory and memory mapped files.
27
justin

J'ai plusieurs threads appelant simultanément Push_back () sur un objet partagé de std :: vector. ... J'espère rechercher des solutions thread-safe existantes pour le vecteur.

Jeter un coup d'œil à concurrent_vector in TBB d'Intel . À strictement parler, c'est assez différent de std::vector en interne et n'est pas entièrement compatible avec l'API, mais peut toujours convenir. Vous pouvez trouver quelques détails sur sa conception et ses fonctionnalités dans les blogs des développeurs TBB .

9
Alexey Kukanov