Heim >Java >javaLernprogramm >Einführung in die Rolle der AtomicInteger-Atomklasse (Codebeispiel)
Dieser Artikel bietet Ihnen eine Einführung in die Rolle der AtomicInteger-Klasse (Codebeispiele). Ich hoffe, dass er für Sie nützlich ist . helfen.
Die Rolle der AtomicInteger-Atomklasse
Multithread-Operation, Synchronized hat zu viel Leistungsaufwand. count++ ist keine atomare Operation. Weil count++ drei Schritte des Lesens, Änderns und Schreibens durchlaufen muss.
count++ ist keine atomare Operation. Weil count++ drei Schritte des Lesens, Änderns und Schreibens durchlaufen muss.
Sie können dies tun:
public synchronized void increase() { count++; }
Synchronisierte Sperre ist exklusiv, was bedeutet, dass der aktuelle Thread nur warten kann, wenn andere Threads ausgeführt werden!
Operation mit CAS
CAS hat 3 Operanden:
Speicherwert V alter erwarteter Wert Ein neuer Wert, der geändert werden soll B, wenn mehrere Threads versuchen Wenn CAS verwendet wird Um dieselbe Variable gleichzeitig zu aktualisieren, kann nur einer der Threads den Wert der Variablen aktualisieren (wenn A und der Speicherwert V gleich sind, ändern Sie den Speicherwert V in B), während andere Threads fehlschlagen Der fehlgeschlagene Thread bleibt nicht hängen. Stattdessen wird Ihnen mitgeteilt, dass Sie den Wettbewerb nicht bestanden haben und es erneut versuchen können (oder nichts unternehmen).
Wir können feststellen, dass es in CAS zwei Situationen gibt:
Wenn der Speicherwert V unserem erwarteten Wert A entspricht, wird der Speicherwert in B geändert und die Operation ist erfolgreich !
Wenn der Speicherwert V nicht unserem erwarteten Wert A entspricht, gibt es im Allgemeinen zwei Situationen:
Erneut versuchen (drehen) und nichts tun
CAS verstehen Der Kern ist :
CAS ist atomar. Auch wenn Sie vielleicht denken, dass es zwei Operationen gibt, nachdem Sie Vergleich und Änderung gesehen haben (Vergleichen und Tauschen), ist es doch atomar!
Die atomare Variablenklasse befindet sich im Paket java.util.concurrent.atomic. Insgesamt gibt es so viele
Grundtypen:
AtomicBoolean: Boolean AtomicInteger: Integer AtomicLong : Long-Integer-Typ
Array:
AtomicIntegerArray: Integer-Typ im Array AtomicLongArray: Long-Integer-Typ im Array AtomicReferenceArray: Referenztyp im Array
Referenztyp:
AtomicReference: Referenztyp AtomicStampedReference: Referenztyp mit Versionsnummer AtomicMarkableReference: Referenztyp mit Markierungsbits
Eigenschaften des Objekts
AtomicIntegerFieldUpdater: Die Eigenschaften des Objekts sind Ganzzahltyp AtomicLongFieldUpdater : Das Attribut des Objekts ist eine lange Ganzzahl AtomicReferenceFieldUpdater: Das Attribut des Objekts ist ein Referenztyp
JDK8 new DoubleAccumulator, LongAccumulator, DoubleAdder, LongAdder
ist eine Verbesserung gegenüber AtomicLong und anderen Klassen. Beispielsweise sind LongAccumulator und LongAdder in Umgebungen mit hoher Parallelität effizienter als AtomicLong. Die Klassen im Atomic-Paket sind grundsätzlich Wrapper-Klassen, die mit Unsafe implementiert werden.
Es gibt mehrere Methoden (CAS), die uns in Unsafe gefallen:
// 第一和第二个参数代表对象的实例以及地址,第三个参数代表期望值,第四个参数代表更新值 public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5); public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5); public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
Die atomare Variablenklasse verwendet
class Count{ // 共享变量(使用AtomicInteger来替代Synchronized锁) private AtomicInteger count = new AtomicInteger(0); public Integer getCount() { return count.get(); } public void increase() { count.incrementAndGet(); } }
ABA-Problem der Atomklasse
Die folgenden Vorgänge können normal ausgeführt werden. Welche Probleme treten in diesem Fall auf? ? Thread C kann die von Thread A und Thread B geänderten Zählwerte nicht kennen, was riskant ist.
Jetzt habe ich eine Variable count=10. Jetzt gibt es drei Threads, nämlich A, B, C. Thread A und Thread C lesen gleichzeitig die Zählvariable, also den Speicherwert und den erwarteten Wert von Thread A und Thread C sind beide 10. Zu diesem Zeitpunkt verwendet Thread A CAS, um den Zählwert auf 100 zu ändern. Nach der Änderung kommt zu diesem Zeitpunkt Thread B herein und liest den Zählwert als 100 (den Speicherwert und). (erwartete Werte sind beide 100) und ändert den Zählwert auf 100. Der Wert wird auf 10 geändert. Thread C erhält die richtige Ausführung und stellt fest, dass der Speicherwert 10 und der erwartete Wert ebenfalls 10 ist. Ändern Sie den Zählwert auf 11
Das ABA-Problem lösen
Um das ABA-Problem zu lösen, können wir die vom JDK bereitgestellten Klassen AtomicStampedReference und AtomicMarkableReference verwenden.
Einfach ausgedrückt stellt es eine Version für dieses Objekt bereit, und wenn diese Version geändert wird, wird sie automatisch aktualisiert.
Das Prinzip ist ungefähr so: Ein Pair-Objekt wird verwaltet und das Pair-Objekt speichert unsere Objektreferenz und einen Stempelwert. Jedes Mal, wenn CAS zwei Paarobjekte vergleicht
LongAdder hat eine bessere Leistung als AtomicLong
Bei Verwendung von AtomicLong konkurrieren viele Threads um die gleichzeitige Aktualisierung derselben atomaren Variablen unter hoher Parallelität. Aufgrund der gleichzeitigen Ausführung ist jedoch nur das CAS eines Threads erfolgreich, sodass andere Threads weiterhin versuchen, CAS-Vorgänge zu drehen und auszuprobieren, was eine Menge CPU-Ressourcen verschwendet.
LongAdder kann wie folgt zusammengefasst werden: Der interne Kerndatenwert wird in ein Array (Zelle) aufgeteilt. Wenn jeder Thread darauf zugreift, wird er durch Hashing und andere Algorithmen einer der Zahlen zugeordnet Das endgültige Zählergebnis ist: Es ist die Summierung und Akkumulation dieses Arrays.
Einfach ausgedrückt wird ein Wert in mehrere Werte aufgeteilt, was den Druck während der Parallelität verteilen und die Leistung verbessern kann.
Das obige ist der detaillierte Inhalt vonEinführung in die Rolle der AtomicInteger-Atomklasse (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!