8
votes

C ++ Accès au vecteur de plusieurs threads

Dans mon programme, j'ai des threads en cours d'exécution. Chaque thread obtient un pointeur sur un objet (dans mon programme - Vector). Et chaque fil modifie le vecteur.

Et parfois, mon programme échoue avec une faute SEGM. Je pensais que cela se produisait parce que le fil a commence à faire quelque chose avec le vecteur pendant que le fil b n'a pas fini de fonctionner avec elle? Peut-il être vrai?

Comment suis-je censé le réparer? Synchronisation de fil? Ou peut-être faire un drapeau vectorisinuse et définir ce drapeau sur true tout en fonctionnant avec celui-ci?


4 commentaires

Vous devez probablement garder les opérations d'écriture avec des mutiles. Notez que même si vous verrouillez les opérations d'écriture, les itérateurs et les références peuvent être invalidés, il n'existe donc aucune solution totalement sûre. Vous ferez mieux de ne pas effectuer de modification des opérations de plus d'un fil.


Bonjour, une faute de segmentation est généralement causée par l'accès à la mémoire qui n'est pas réservée par votre processus. Pourrait-il être que vous utilisez quelque chose comme un pointeur qui n'est en réalité pas un pointeur? Sinon, consultez ceci: Stackoverflow.com/questions/1099513 / ...


@juanchopanza - pas seulement les opérations d'écriture, toutes les opérations . Chaque accès aux données partagés doit être protégé.


@Petebecker a accepté et certains accès (par exemple référence aux éléments du conteneur ou des itérateurs), vous ne pouvez pas vraiment protéger de toute façon ...


3 Réponses :


0
votes

C'est pourquoi la bibliothèque de classe qui offre des threads a également des primitives de synchronisation telles que les mutexes / serrures. Vous devez configurer l'un d'entre eux, et éroger / relâcher la serrure autour de chaque opération sur l'élément partagé (options de lecture et d'écriture, puisque vous devez empêcher les lectures de l'occultation pendant une écriture aussi, n'empêchez pas seulement les écrivies multiples qui se produisent simultanément). < / p>


0 commentaires

13
votes

vecteur , comme tous les conteneurs STL, ne sont pas thread-coffre-fort. Vous devez explicitement gérer la synchronisation vous-même. Un std :: mutex ou boost :: mutex pourrait être utilisé pour synchroniser l'accès au vecteur .

N'utilisez pas de drapeau car il n'est pas thread-coffre-fort:

  • thread une valeur de contrôle de isinuse drapeau et c'est false
  • Le fil A est suspendu
  • thread b vérifie la valeur de isinuse drapeau et c'est false
  • thread b ensembles isinuse à true
  • thread b est suspendu
  • Le fil A est repris
  • thread a toujours pense isinuse est false et le définit true
  • thread a et thread b maintenant a accès au vecteur

    Notez que chaque thread devra verser le vecteur pendant tout le temps nécessaire à l'utiliser. Cela inclut la modification du vecteur Vecteur car les itérateurs peuvent devenir invalidés si l'élément à laquelle ils se réfèrent sont effacer () ou vecteur subit une réaffectation interne. Par exemple ne pas: xxx


6 commentaires

Méfiez-vous que les itérateurs et les références peuvent être invalidés et que vous ne pouvez pas protéger contre cela avec des mutiles.


@juanchopanza, Yep. Était toujours à jour.


Volontier. J'ai complètement mal interprété votre réponse. J'ai vu l'échantillon de code et j'étais comme "Whaaa Epic Fil!". Ensuite, j'étais comme "Oh, attends".


En tout état de cause, devoir se rappeler explicitement de verrouiller le mutex avant d'utiliser le vecteur est assez dangereux, car rien n'empêche mal utilisé accidentellement, et rien n'empêche les itérateurs de fuir. Un concurrent_vector est beaucoup plus sûr.


@Deadmg, est Concurrent_vector Microsoft uniquement?


Il y a aussi un à TBB, qui est fondamentalement le même principe.



4
votes

Si vous souhaitez utiliser un conteneur à utiliser à partir de nombreux threads, vous devez utiliser un conteneur explicitement conçu à cet effet. L'interface des conteneurs standard n'est pas conçue pour une mutation simultanée ni une sorte de concurrence, et vous ne pouvez pas simplement lancer un verrou au problème.

Vous avez besoin de quelque chose comme TBB ou PPL qui a Concurrent_vector .


0 commentaires