2011-08-26 2 views

Répondre

3

L'idée que l'appel find(...)->second est thread-safe est très dépendante de votre vue de thread-safety. Si vous voulez simplement dire que ça ne va pas tomber, alors tant que personne ne mute le dictionnaire en même temps que vous le lisez, je suppose que vous allez bien.

Cela dit, en effet, peu importe ce que vos exigences de sécurité minimales de fil sont, appeler la méthode operator[] est intrinsèquement pas thread-safe car il peut muter la collection. Si une méthode n'a pas de surcharge const, cela signifie qu'elle peut muter l'objet, donc à moins que la documentation indique que les méthodes sont thread-safe, la méthode est très peu probable.

Là encore, une méthode const pourrait ne pas être thread-safe ainsi, parce que votre objet pourrait dépendre de l'état global non const ou ont mutable champs, de sorte que vous aurez envie d'être très, très prudent si vous utilisez désynchronisé classes comme si elles étaient.

0

Vous avez raison, operator[] n'est pas "thread-safe" car il peut muter le conteneur. Vous devriez utiliser la méthode find et comparer le résultat à std::map::end pour voir si elle a trouvé l'élément. (Notez également que find a une version const alors que operator[] ne l'est pas).

Comme d'autres l'ont dit, la version de C++ avant C++ 11 n'a pas de notion de thread ou de sécurité de thread. Cependant, vous pouvez vous sentir en sécurité en utilisant find sans synchronisation car il ne change pas le conteneur, donc il ne fait que des opérations de lecture (sauf si vous avez une implémentation bizarre, alors assurez-vous de vérifier les docs). Comme avec la plupart des conteneurs, la lecture à partir de différents threads ne causera aucun dommage, mais l'écriture pourrait le faire.

+0

Vous ne pouvez pas "vous sentir en sécurité en utilisant' find "sans synchronisation" s'il y a la possibilité d'une opération d'écriture simultanée. –

+0

@Emile si vous le dites, je vous crois, mais pourquoi est-ce? Que pourrait-il arriver si vous utilisez 'find' alors qu'un autre thread écrit dans le conteneur? Et pourquoi n'avez-vous pas aussi critiqué la réponse d'André puisque c'est aussi "faux"? –

+0

J'ai fait la réponse négative d'André. :-) Utiliser find comme vous le suggérez n'est pas thread safe car ce n'est pas une opération atomique. Une opération d'écriture simultanée perturbera l'état interne de la carte sans que 'find 'ne le sache. Par exemple, que se passe-t-il si un nœud que 'find' traverse est soudainement supprimé? –

1

Les conteneurs de bibliothèque standard n'ont aucune notion de sécurité des threads. Vous devez synchroniser vous-même l'accès en lecture/écriture simultané au conteneur.

try n'a rien à voir avec le multithreading. Il est utilisé pour la gestion des exceptions.

find ne déclenche pas d'exception si la clé n'est pas trouvée. Si la clé n'est pas trouvée, find renvoie l'itérateur end() de la carte.

+0

Je pense qu'il a pensé 'trouver' a jeté une exception quand il n'a pas trouvé l'article, je ne pense pas qu'il était utilisé pour la sécurité du fil. –

+0

essayer n'a rien à voir avec multithreading - je suis d'accord mais en cas de trouver (..) -> deuxième n'existe pas d'erreur sera jeté et nous aurions à créer de nouveau tout ce que nous cherchions, le remplir avec des données verrouiller le mutex et insérez de nouvelles données dans la carte. – Rella

+1

@Kabumbus Selon [ce site] (http://www.cplusplus.com/reference/stl/map/find/) 'find' il ne lance pas d'exception mais retourne' std :: map :: end' quand l'article n'existe pas –

2

Si vous êtes sûr à 100% que la carte contient la clé, alors il est techniquement thread-safe si tous les autres threads n'appellent également que des méthodes en lecture seule sur la carte. Notez cependant qu'il n'y a pas de version const de map<k,v>::operator[](const k&).

La bonne façon d'accéder à la carte dans un mode thread-safe est en effet:

map<k,v>::const_iterator match = mymap.find(key); 
if (match != mymap.end()) { 
    // found item. 
} 

Comme indiqué précédemment, cela ne vaut que si tout accès simultané est en lecture seule. Une façon de garantir cela est d'utiliser un readers-writers lock.

Notez qu'en C++ 03, il n'y a aucune mention de threads dans la norme, même si cela n'est pas garanti pour être thread-safe. Assurez-vous de vérifier la documentation de votre implémentation.

+0

Et en C++ 11? =) – Rella

+1

Comment pouvez-vous dire que c'est la manière correcte d'accéder à la carte de manière thread-safe? Comment savez-vous qu'il n'existe aucune opération d'écriture simultanée qui peut déplacer l'itérateur final? –

+0

@Kabumbus, en C++ 03, la norme ne reconnaissait même pas les threads, donc une question comme la vôtre n'a pas de sens (par rapport à la norme). En C++ 11, les threads sont reconnus, mais ce que vous demandez est spécifié comme étant un comportement indéfini. – zneak

Questions connexes