Nehmen wir an, ich habe einen Vektor von N Elementen, aber bis zu n Elemente dieses Vektors haben aussagekräftige Daten. Ein Aktualisierungsthread aktualisiert das n-te oder n + 1te Element (setzt dann n = n + 1), prüft auch, ob n zu nah an N ist, und ruft vector :: resize (N + M) auf, falls erforderlich. Nach dem Aktualisieren ruft der Thread mehrere untergeordnete Threads auf, um bis zu n-ten Daten zu lesen und einige Berechnungen durchzuführen.STL-Vektor und Thread-Sicherheit
Es ist garantiert, dass untergeordnete Threads niemals Daten ändern oder löschen (tatsächlich werden überhaupt keine Daten gelöscht), und das Updater ruft untergeordnete Elemente direkt nach Abschluss der Aktualisierung auf.
Bis jetzt ist kein Problem aufgetreten, aber ich möchte fragen, ob ein Problem bei der Neuzuordnung des Vektors zu einem größeren Speicherblock auftreten kann, wenn noch einige untergeordnete Threads vom vorherigen Update übrig sind.
Oder ist es sicher, in einem solchen Multithread-Fall Vektor zu verwenden, da es nicht Thread-sicher ist?
EDIT: Da nur Einfügen erfolgt, wenn der Updater vector :: resize (N + M, 0) aufruft, gibt es mögliche Lösungen für mein Problem? Aufgrund der großen Leistungsfähigkeit des STL-Vektors bin ich nicht bereit, ihn durch einen sperrbaren Vektor zu ersetzen, oder in diesem Fall gibt es irgendwelche performanten, bekannten und sperrfreien Vektoren?
@James McNellis: Ja. Das ist ein guter Rat.Ich kann die Umverteilung selbst vornehmen. Tatsächlich sind Vektoren innerhalb einer Klasse eingeschlossen, die einen Zeiger auf Vektor enthält. Es ist nicht shared_ptr, aber ich kann leicht einen neuen größeren Vektor konstruieren, Elemente aus dem alten kopieren, löschen. Also, was ist der schnellste Weg, um einen großen Speicherblock zu kopieren. Kopiespeicher()? –
Wäre es nicht einfacher, anstelle eines Vektors 'std :: deque' zu verwenden? Das vermeidet die Neuzuweisungen vollständig und bietet dennoch eine Leistung, die fast gleichwertig mit Vektor ist. – jalf
@jalf: Ich glaube nicht, dass es sicher ist, ein 'std :: deque' zu verwenden, da Umplatzierungen nicht die einzige Sorge sind. Es gibt keine Garantie, dass 'std :: deque :: operator []' nicht die Größe oder eine der anderen Buchhaltungen innerhalb der 'Deque' überprüft. Es besteht also die Möglichkeit für eine Race-Bedingung, bei der ein Verbraucher 'operator' aufruft. ', der den internen Zustand liest, während der Erzeuger Daten hinzufügt, die den internen Zustand ändert. –