Vorbedingungen (allgemeine Beschreibung) :
1. statisches Klassenfeld
%Vor% 2. CompletableFuture#runAsync(Runnable runnable,Executor executor)
wird innerhalb aufgerufen
static void main(String args[])
Methode
3. Elemente, die zu someCollection
innerhalb von runAsync
hinzugefügt wurden, rufen Sie von step2
Code-Snippet (spezifische Beschreibung) :
%Vor%Problembeschreibung:
Wie ich aus dem Gesichtspunkt der Gleichzeitigkeit verstehe, statische Variable kann NICHT zwischen Threads geteilt werden, so dass Daten auf irgendeine Weise verloren gehen können.
Sollte es in volatile
geändert werden oder wäre es sinnvoll zu verwenden
ConcurrentSkipListSet<String>
?
Basierend auf dem Codeausschnitt:
volatile
ist hier nicht erforderlich, da es auf der Referenzebene funktioniert, während die Aufgaben die Referenz des Sammlungsobjekts nicht aktualisieren, sondern ihren Status mutieren. Wird der Verweis aktualisiert, wurde möglicherweise volatile
oder AtomicReference
verwendet.
Statisches Objekt kann zwischen Threads geteilt werden, aber das Objekt muss Thread-sicher sein. Eine gleichzeitige Sammlung übernimmt die Aufgabe für leichte bis mittlere Belastung.
Aber die moderne Art, dies zu tun, würde Streams beinhalten, anstatt eine gemeinsame Sammlung zu verwenden:
%Vor%In Ihrem speziellen Fall gibt es Möglichkeiten, die Thread-Sicherheit für IDs zu garantieren:
Beispiele für synchronisierte:
%Vor%Ich nehme an, dass es am schnellsten wäre, Collections.newSetFromMap (new ConcurrentHashMap () zu verwenden, wenn Sie viele Benutzer-IDs erwarten. Andernfalls wären Sie mit ConcurrentSkipListSet vertraut.
volatile ist hier eine schlechte Wahl. Volatile garantiert Sichtbarkeit, aber nicht Atomizität. Die typischen Beispiele für flüchtige Verwendung sind
%Vor%In diesem Fall schreiben / lesen Sie nur einmal. Da "a" flüchtig ist, ist garantiert, dass jeder Thread genau 1 oder 2 "sieht" (lesen). Ein anderes (schlechtes Beispiel):
%Vor%Hier erhöhen wir die Operation (lesen und schreiben) und es gibt verschiedene Ergebnisse von a, weil wir keine Atomizität haben. Deshalb gibt es AtomicInteger, AtomicLong, etc. In Ihrem Fall würden alle Threads die Schreib-IDs sehen, aber sie würden unterschiedliche Werte schreiben und wenn Sie innerhalb der "add" -Methode von ArrayList sehen, sehen Sie etwas wie:
%Vor%So niemand garantiert Atomizität der Größe, Sie könnten verschiedene ID in einer Array-Zelle schreiben.
In Bezug auf die Fadensicherheit ist es egal, ob die Variable statisch ist oder nicht. Was zählt, ist
Ihr Codebeispiel ist aus Sicht der Sichtbarkeit in Ordnung, weil ids
statisch ist und während der Klassenerstellungszeit initialisiert wird. Es ist jedoch besser, sie als final
oder volatile
zu markieren, abhängig davon, ob ids
reference geändert werden kann. Die Sicherheit wird jedoch verletzt, da ArrayList
ihre Invarianten in der Multithread-Umgebung nicht vom Design aus bewahrt. Sie sollten also eine Sammlung verwenden, die für den Zugriff durch mehrere Threads ausgelegt ist. Dieses Thema sollte bei der Auswahl helfen.
Tags und Links java static field updating completable-future