Was bedeutet es, ein dynamisches Array threadsicher und gleichzeitig zu machen? Sagen Sie beispielsweise %code% .
Gibt es also etwas, das über %code% erledigt werden muss, um es threadsicher und gleichzeitig zu machen oder ist es threadsicher und gleichzeitig standardmäßig?
Die einzigen gleichzeitigen Operationen für ein einzelnes Objekt in der Standardbibliothek, die standardmäßig sicher sind, sind - Nur Zugriff auf %code% -Member Funktionen - Alle Zugriffe auf Synchronisationsprimitive (wie Mutex Lock und Unlock oder atomare Operationen) Alles andere muss extern synchronisiert werden. Insbesondere hat die Standardbibliothek noch keine threadsicheren Container (ab c ++ 14)
Die Antwort auf beide Beispiele ist also nein, beide erfordern eine Form der externen Synchronisation.
Sie können natürlich den Wert zweier verschiedener Elemente im Container ändern.
C ++ 11 sagt Folgendes über die Thread-Sicherheit von Containern in der Standardbibliothek:
23.2.2 Containerdatenrassen [container.requirements.dataraces]
Zum Zweck der Vermeidung von Datenrennen (17.6.5.9) müssen Implementierungen Betrachte die folgenden Funktionen als const: %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% , %code% und, außer in assoziativen oder ungeordnete assoziative Container, %code% .
Ungeachtet (17.6.5.9) sind Implementierungen erforderlich, um Daten zu vermeiden Rennen, wenn der Inhalt des enthaltenen Objekts in verschiedenen Elementen in der gleichen Reihenfolge, mit Ausnahme von %code% , werden geändert gleichzeitig.
Das Lesen von einem Container aus mehreren Threads ist also in Ordnung, und das Modifizieren von Elementen, die sich bereits im Container befinden, ist in Ordnung (solange sie verschiedene Elemente sind).
Daher ist keine der beiden spezifischeren Fragen für %code% threadsicher:
1) Zwei Threads, die in den Vektor eingefügt werden, modifizieren den Vektor selbst - keine existierenden separaten Elemente.
2) Das Löschen eines Threads und anderes Gehen, um auf dasselbe Element zuzugreifen, ist nicht sicher, da das Löschen eines Elements aus dem Vektor keine Operation ist, die threadsicher ist (oder "frei von Datenrennen" wie der Standard) setzt es).
Um diese Operationen sicher ausführen zu können, muss das Programm eine externe Synchronisation selbst vornehmen.
Ich habe versucht, über die verschiedenen Datenstrukturen zu lernen, die in populären Sprachen verwendet werden, wie Listen und Wörterbücher in Python, assoziative Arrays in PHP (im Wesentlichen Hash-Tabellen), Vektoren in C ++, usw.
Ich habe eine Menge Kollegen, die R religiös verwenden, und ich habe mich gefragt, wie Vektoren, Matrizen und Datenrahmen in R implementiert werden. Was sind ihre Stärken und Schwächen? Ich habe den Quellcode durchgesehen, aber ich konnte die Datenstrukturen nicht selbst finden. Wo befinden sich diese Definitionen im Quellcode?
Wie bereits erwähnt, schauen Sie sich auch das Handbuch "R internals" an als diesen Teil von "Writing R extensions" .
Ein bisschen spät, aber wollte einen Fehler mit einer der anderen Antworten aufzeigen und eine explizite Antwort geben. Sehen Sie sich das Handbuch für Internes an:
Lesen Sie den Anfang dieses Abschnitts und den Eintrag für 'INTSXP'. Es scheint, dass ganzzahlige Vektoren als ein Array von C int implementiert sind. Ähnlich für 'REALSXP' und 'CHARSXP'.
Die Implementierung als verknüpfte Listen wäre zu langsam gewesen.
Von R Internals, 1.1 SEXPs:
... die Grundbausteine von R-Objekten werden oft Knoten genannt ... Beide Typen von Knotenstrukturen haben als ihre ersten drei Felder einen 32-Bit-spxinfo-Header und dann drei Zeiger (zu den Attributen und dem vorherigen und nächsten Knoten in einer doppelt verknüpften Liste)
Daher sind Vektoren in R als doppelt verknüpfte Liste implementiert. Und es scheint sogar, dass es keine Datenstruktur gibt, die kleiner als eine verknüpfte Liste mit einem einzigen Knoten ist. Dies wird offensichtlich durch:
%Vor%Wie von anderen erwähnt: %code% hat %code% und %code% und %code% hat die Quelle für %code% . Zusätzlich enthält %code% die Quelle für %code% und %code% enthält die Quelle für %code% .
Während viele Dinge, die sich abspielten, über meinem Kopf lagen, scheint es offensichtlich, dass eine Matrix einfach eine doppelt verknüpfte Liste doppelt verknüpfter Listen ist. Ich glaube (obwohl ich nicht sicher bin), dass Zeilen- und Spaltennamen (wie die in einem Datenrahmen gespeicherten) in den 'Attributen' jeder Liste gespeichert sind.
Die Antwort auf die "Was die Stärken und Schwächen" der Implementierung der Datenstrukturen wäre, dass (aus meinem begrenzten Wissen) doppelt verknüpfte Listen eine Stärke darin haben, dass die dynamische Speicherzuweisung einfacher ist und keinen Overhead erfordert Kopieren und Neuzuweisen eines gesamten Arrays, und die Schwäche ist, dass (abhängig davon, wie viele Zeiger auf die Liste sind: Kopf, Schwanz, Mitte, Viertel usw.) der Zugriff auf einen zufälligen Wert %code% den Overhead des Iterierens in Anspruch nehmen kann mehrere Elemente vor dem gewünschten gefunden.
Stimmt das?