Ich habe eine Multithread-Anwendung und eine freigegebene Ressource std::map<KeyType, ElementType>
. Ich benutze einen Mutex, um Einfügungen zu schützen, bekommt und entfernt.
Meine get-Methode gibt einen Verweis auf das gespeicherte Element zurück (wird bei der Rückkehr wieder entsperrt), und dann arbeite ich mit diesem Element.
Frage: Ist es möglich, dass während der Arbeit mit der gespeicherten Elementreferenz ein anderer Thread std::map
ändert, sodass das Element an eine andere Adresse verschoben wird und die Referenz nicht mehr gültig ist ? (Ich weiß, dass es bestimmte ADT-Implementierungen gibt, die eine Umordnung des ADT bei der Größenänderung durchführen).
Die Iterator-Invalidierungsregel für assoziative Container (wobei std::map
lautet) lautet unter [assoziativ. Anforderungen] / 9 :
Die Mitglieder von insert und emplace dürfen die Gültigkeit von Iteratoren und Verweise auf den Container und die Löschelemente müssen mache nur Iteratoren und Referenzen auf die gelöschten Elemente ungültig.
Wenn also ein Thread ein Element einfügt, wirkt sich das nicht auf Referenzen auf vorhandene Elemente aus. Wenn es jedoch etwas entfernt, können andere Threads geborst werden. Irgendeine Form der elementweisen Verriegelung ist in Ordnung, würde ich sagen.
Ein anderer Thread kann das Element löschen oder die Karte zerstören, was natürlich auch das Element ungültig machen würde.
Das Löschen eines Elements macht nur Iteratoren und Refewrences für dieses Element ungültig. Durch das Einfügen werden Iteratoren oder Verweise nicht in die Map ungültig.
(so heißt es zumindest in der Dokumentation aus zweiter Hand ) - und das ist eine Annahme Ich halte das nie für ungültig, wenn Einzelfälle zählen.)
Ein weiteres Problem bleibt: Die Manipulation des Elements durch die zurückgegebene Referenz ist nicht Thread-sicher. Sie müssen z. pro Element - und stellen Sie sicher, dass Sie die Sperrhierarchie nicht verletzen.
Tags und Links c++ multithreading c++11 std