Dieser Artikel untersucht hauptsächlich inhaltliche Inhalte über ABA -Probleme und Vermeidung in Java wie folgt.
In Kapitel 15 des Buches "Java Concurrency Practication Practice" wird ein Stapel mit Atomvariablen implementiert, und der Code lautet wie folgt:
public class Node {public Final String Element; öffentlicher Knoten als nächstes; öffentlicher Knoten (String -Element) {this.item = item;}} public class concurrentStack {atomicreference <node> top = new atomicreference <node> (); public void push (String item) {node newtop = new node (item); node oldtop; do {Oldtop = top.get (); newtop.Next = oldTop; pop () {node newtop; node oldtop; do {oldtop = top.get (); if (oldtop == null) {return null;} newtop = oldtop.next;} while (! top.comPareAnDSet (oldtop, newtop));Dieses Beispiel verursacht keine ABA -Probleme. Warum es nicht ist, werde ich es später erklären. Sprechen wir zuerst über die ABA -Probleme.
Was ist ABA?
Zitieren Sie das Originalbuch: Wenn die Knoten im Algorithmus zyklisch verwendet werden können, kann dieses Problem bei Verwendung der Anweisung "Vergleich und Austausch" auftreten. In der CAS -Operation wird beurteilt, dass "der Wert von V immer noch a?", Und wenn ja, wird die Aktualisierungsoperation fortgesetzt. Wenn in einigen Algorithmen sich der Wert von V zuerst von A nach B und dann von B nach A ändert, wird CAS erfolgreich funktionieren.
Beispiele für ABA
Manchmal sind die durch ABA verursachten Folgen sehr schwerwiegend. Ändern wir das Beispiel des Parallelitätsstapels, um zu sehen, welche Probleme ABA verursachen werden:
public class Node {public Final String Element; öffentlicher Knoten als nächstes; öffentlicher Knoten (String -Element) {this.item = item;}} public class ConcurrentStack {AtomicReference<Node> top = new AtomicReference<Node>();public void push(Node node){Node oldTop;do{oldTop = top.get();node.next = oldTop;}while(!top.compareAndSet(oldTop, node));}public Node pop(int time){Node newTop;Node oldtop; do {oldtop = top.get (); if (oldtop == null) {return null;} newtop = oldTop.Next; TimeUnit.seconds.sleep (Zeit);} while (! top.comPareAndset (oldtop, newtop));Achten Sie auf die Änderungen hier, der Knoten hat sich im Grunde nicht geändert
Konzentrieren Sie sich auf die Veränderungen in ConcurrentStack
1. Push -Methode: Ursprünglich mit dem Inhalt zum Konstruktion von Knoten, aber jetzt direkt in den Knoten übergeben, was den Anforderungen von "Knoten im Algorithmus recycelt werden kann".
2. Der Schlaf der POP -Methode, der die Ausführung des Threads simuliert, um die Ergebnisse zu beobachten.
Lassen Sie uns zuerst zwei Knoten in den Stapel drücken:
ConcurrentStack Stack = New ConcurrentStack (); stack.push (neuer Knoten ("a")); stack.push (neuer Knoten ("B"));Erstellen Sie dann zwei Threads, um Operationen durchzuführen und den Stapel zu verlassen und zu verlassen
Thread A Führen Sie zuerst das Stapel aus: Lassen Sie Nodea aus dem Stapel
stack.pop (3);
Aus irgendeinem Grund wurde Thread A seit langem ausgeführt und hat 3 Sekunden verwendet
Thread B führt den Stapel aus und tritt dann in den Stapel ein: Zuerst werden Nodea und NodeB freigegeben und dann nicken, nodec und nodea eingegeben werden (Nodea befindet sich oben am Stapel)
Knoten a = stack.pop (0); stack.pop (0); stack.push (neuer Knoten ("D")); stack.push (neuer Knoten ("C")); stack.push (a);Hinweis: Thread B implementiert das Recycling von Knoten. Es gibt zuerst alle Inhalte im Stapel frei und bringt sie dann in den Stapel. Schließlich ist der Inhalt oben im Stapel der Knoten, der zuvor veröffentlicht wurde.
Nachdem Thread B diese Aktionen ausgeführt hat, wird Thread A CAS ausführen. Zu diesem Zeitpunkt kann CAS erfolgreich ausführen.
Nach der ursprünglichen Idee sollte nach der Ausführung von Threads A und B der Inhalt des Stacks sein: C und D, C befindet sich oben am Stapel, aber das Ausführungsergebnis hier ist, dass es in Stack nichts gibt, was das ABA -Problem ist.
Wie man ABA -Probleme vermeidet
AtomicStampedReference und AtomicmarkableReference werden in Java zur Lösung von ABA -Problemen bereitgestellt
AtomicStampedReference kann zwei Werte atomisch aktualisieren: Referenz- und Versionsnummer und die Zyklusverbrauch des Knotens nach Versionsnummer unterscheiden. Lassen Sie uns das Beispiel von AtomicStampedReference sehen:
public class concurrentStack {atomicStampedReference <Knode> top = new AtomicStampedReference <Knode> (null, 0); public void push (node node) {node oldtop; int v; do {v = top.getStstamp (); Oldtop = top.getreference (); Node, v, v+1)); //} while (! top.crPareAndset (Oldtop, Knoten, top.getStamp (), top.getStamp ()+1);} public node pop (int time) {node newtop; node oldtop; int v; do {v = top.Ge = oldstamp (); oldtop (); oldtop = oldtop = oldtop = oldtop = oldtop = oldtop); null;} newtop = oldtop.next; try {timeUnit.seconds.sleep (time);} catch (interruptedException e) {e.printstacktrace ();}} while (! top.comPareandset (oldtop, newtop, v, v+1)); newtop, top.getStamp (), top.getStamp ())); return OldTop;} public void get () {node node = top.getReferation (); while (node!Hinweis: Sie können die Kommentierungsmethode nicht verwenden, andernfalls unterscheidet sie sich nicht von der Verwendung von Atomvariablen.
AtomicmarkableReferenferenference kann eine boolesche Typ -Marker -Bits und -referenztypen atomisch aktualisieren, siehe das folgende Beispiel:
AtomicmarkableReenference <node> top = new atomicmarkableReference <Knode> (null, true); public void push (Knotenknoten) {Knoten Oldtop; boolean v; do {v = top.ismarked (); Oldtop = top.getreferenz ();Zusammenfassen
Das oben genannte ist der gesamte Inhalt dieses Artikels über kurze Diskussionen über ABA -Probleme und Vermeidung von Java. Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!