logo

Java Atomic

In Java, atomare Variablen Und Operationen im Parallelbetrieb verwendet. Der Multithreading Umgebung führt zu einem Problem, wenn Parallelität ist einheitlich. Die gemeinsam genutzten Entitäten wie Objekte und Variablen können während der Ausführung des Programms geändert werden. Sie können daher zu einer Inkonsistenz des Programms führen. Daher ist es wichtig, beim gleichzeitigen Zugriff auf die gemeinsame Entität zu achten. In solchen Fällen ist die atomare Variable kann eine Lösung dafür sein. In diesem Abschnitt werden wir diskutieren Atomklassen, Atomvariablen, Atomoperationen , zusammen mit Beispielen.

Python OS Listdir

Bevor Sie mit diesem Abschnitt fortfahren, stellen Sie sicher, dass Sie sich darüber im Klaren sind Faden , Synchronisation , Und sperren in Java.

Atomare Java-Klassen

Java bietet eine java.util.concurrent.atomic Paket, in dem atomare Klassen definiert sind. Die Atomklassen bieten a sperrfrei Und Thread-sicher Umgebung oder Programmierung auf einer einzelnen Variablen. Es unterstützt auch atomare Operationen. Alle atomaren Klassen verfügen über die Methoden get() und set(), die mit der flüchtigen Variablen arbeiten. Die Methode funktioniert genauso wie das Lesen und Schreiben von flüchtigen Variablen.

Das Paket stellt die folgenden atomaren Klassen bereit:

Klasse Beschreibung
AtomicBoolean Es wird verwendet, um boolesche Werte atomar zu aktualisieren.
AtomicInteger Es wird verwendet, um ganzzahlige Werte atomar zu aktualisieren.
AtomicIntegerArray Ein int-Array, in dem Elemente atomar aktualisiert werden können.
AtomicIntegerFieldUpdater Ein reflexionsbasiertes Dienstprogramm, das atomare Aktualisierungen für bestimmte flüchtige Int-Felder bestimmter Klassen ermöglicht.
AtomicLong Es wird verwendet, um lange Werte atomar zu aktualisieren.
AtomicLongArray Ein langes Array, in dem Elemente atomar aktualisiert werden können.
AtomicLongFieldUpdater Ein reflexionsbasiertes Dienstprogramm, das atomare Aktualisierungen für bestimmte flüchtige lange Felder bestimmter Klassen ermöglicht.
AtomicMarkableReference Eine AtomicMarkableReference verwaltet eine Objektreferenz zusammen mit einem Markierungsbit, das atomar aktualisiert werden kann.
AtomicReference Eine Objektreferenz, die atomar aktualisiert werden kann.
AtomicReferenceArray Ein Array von Objektreferenzen, in denen Elemente atomar aktualisiert werden können.
AtomicReferenceFieldUpdater Ein reflexionsbasiertes Dienstprogramm, das atomare Aktualisierungen für bestimmte flüchtige Referenzfelder bestimmter Klassen ermöglicht.
AtomicStampedReference Eine AtomicStampedReference verwaltet eine Objektreferenz zusammen mit einem ganzzahligen „Stempel“, der atomar aktualisiert werden kann.
Doppelakkumulator Eine oder mehrere Variablen, die zusammen einen laufenden Double-Wert verwalten, der mithilfe einer bereitgestellten Funktion aktualisiert wird.
DoubleAdder Eine oder mehrere Variablen, die zusammen eine anfänglich Null-Doppelsumme aufrechterhalten.
LongAccumulator Eine oder mehrere Variablen, die zusammen einen laufenden Long-Wert verwalten, der mithilfe einer bereitgestellten Funktion aktualisiert wird.
LongAdder Eine oder mehrere Variablen, die zusammen eine anfänglich Null-Langsumme beibehalten.

Objekte dieser Klassen repräsentieren die atomare Variable von int, long, boolean , und Objekt Referenz jeweils. Die Atomklassen haben einige gemeinsame Methoden:

Methoden Beschreibung
Satz() Es wird verwendet, um den Wert festzulegen.
erhalten() Es wird verwendet, um den aktuellen Wert zu ermitteln.
lazySet() Wird schließlich auf den angegebenen Wert gesetzt.
vergleichenAndSet Setzt den Wert atomar auf den angegebenen aktualisierten Wert, wenn der aktuelle Wert == der erwartete Wert ist.

Atomare Operationen

Die Operationen, die immer zusammen ausgeführt werden, werden als bezeichnet atomare Operationen oder atomare Aktion . Alle atomaren Operationen werden entweder auf einmal effektiv ausgeführt oder überhaupt nicht ausgeführt. Drei Schlüsselkonzepte, die mit atomaren Aktionen in Java verbunden sind, sind wie folgt:

1. Atomarität befasst sich mit den Aktionen und Mengen von Aktionen unsichtbar Betrachten Sie beispielsweise den folgenden Codeausschnitt:

 class NoAtomicOps { long counter=0; void increment() { for(;;) { count++; } } void decrement() { for(;;) { count--; } } //other statement } 

Im obigen Code ist das Verhalten beim gleichzeitigen Ausführen von inkrementieren () und dekrementieren (). nicht definiert Und nicht vorhersehbar .

2. Die Sichtbarkeit bestimmt, wann die Wirkung eines Threads sein kann gesehen von einem anderen. Betrachten Sie beispielsweise den folgenden Codeausschnitt:

Runde Mathematik Java
 class InfiniteLoop { boolean done= false; void work() { //thread T2 read while(!done) { //do work } } void stopWork() { //thread T1 write done=true; } //statements } 

Im obigen Code ist es möglich, dass Thread T2 niemals stoppt, selbst nachdem Thread T1 done auf true gesetzt hat. Auch nicht, dass es keine Synchronisierung zwischen Threads gibt.

3. Die Reihenfolge bestimmt, wann Aktionen in einem Thread in Bezug auf einen anderen Thread in einer anderen Reihenfolge erfolgen.

 class Order { boolean a=false; boolean b=false; void demo1() //thread T1 { a=true; b=true; } boolean demo2() //thread T2 { boolean r1=b; //sees true boolean r2=a; //sees false boolean r3=a; //sees true //returns true return (r1 && !r2) && r3; } } 

Die Reihenfolge, in der die Felder a und b in Thread T2 angezeigt werden, kann von der Reihenfolge abweichen, in der sie in Thread T1 festgelegt wurden.

Lassen Sie es uns anhand eines Beispiels verstehen.

 public class AtomicExample { int count; public void incrementCount() { count=1; } 

Im obigen Codeausschnitt haben wir eine Variable vom Typ int deklariert zählen und innerhalb der Methode incrementCount() wurde es auf 1 zugewiesen. In einem solchen Fall passieren entweder alle zusammen oder es würde überhaupt nicht passieren. Daher stellt es eine dar Atomoperation und die Operation heißt Atomizität .

Betrachten wir einen weiteren Codeausschnitt.

 public class AtomicExample { int count; public void incrementCount() { count=count+1; } 

Es scheint, dass es sich ebenfalls um eine atomare Operation handelt, aber das ist nicht der Fall. Es handelt sich um eine lineare Operation, die aus drei Operationen besteht, nämlich Lesen, Ändern und Schreiben. Daher kann es teilweise ausgeführt werden. Wenn wir den obigen Code jedoch in einer Multithread-Umgebung verwenden, entsteht ein Problem.

Angenommen, wir haben den obigen Code in einer Single-Thread-Umgebung aufgerufen, ist der aktualisierte Wert von count 2. Wenn wir die obige Methode von zwei separaten Threads aufrufen, greifen beide gleichzeitig auf die Variable zu und aktualisieren auch den Wert von gleichzeitig zählen. Um diese Situation zu vermeiden, verwenden wir eine atomare Operation.

Lambda-Funktion Java

Java unterstützt mehrere Arten von atomaren Aktionen:

  • Flüchtig Variablen
  • Atomare Operationen auf niedriger Ebene (unsicher)
  • Atomare Klassen

Mal sehen, wie wir eine atomare Operation erstellen können.

Atomare Variable

Die atomare Variable ermöglicht es uns, eine atomare Operation an einer Variablen durchzuführen. Atomare Variablen minimieren die Synchronisierung und helfen, Speicherkonsistenzfehler zu vermeiden. Somit ist die Synchronisierung gewährleistet.

Das Atompaket stellt die folgenden fünf Atomvariablen bereit:

Maschinensprache
  • AtomicInteger
  • AtomicLong
  • AtomicBoolean
  • AtomicIntegerArray
  • AtomicLongArray

Die Notwendigkeit einer atomaren Variablen

Betrachten wir den folgenden Code.

Counter.java

 class Counter extends Thread { // Counter Variable int count = 0; //the method starts the execution of a thread public void run() { int max = 1; //increments the counter variable up to specified max time for (int i = 0; i <max; i++) { count++; } public class counter static void main(string args[]) throws interruptedexception creating an instance of the c="new" counter(); four threads thread t1="new" thread(c, 'first'); t2="new" 'second'); t3="new" 'third'); t4="new" 'fourth'); by calling start() method, we have started t1.start(); t2.start(); t3.start(); t4.start(); main will wait for all until execution do not complete t1.join(); t2.join(); t3.join(); t4.join(); prints final value count variable system.out.println(c.count); < pre> <p> <strong>Output:</strong> </p> <pre> 4 </pre> <p>The above program gives the expected output if it is executed in a single-threaded environment. A multi-threaded environment may lead to unexpected output. The reason behind it that when two or more threads try to update the value at the same time then it may not update properly.</p> <p>Java offers <strong>two</strong> solutions to overcome this problem:</p> <ul> <li>By using lock and synchronization</li> <li>By using atomic variable</li> </ul> <p>Let&apos;s create a Java program and use an atomic variable to overcome the problem.</p> <h3>By using Atomic Variable</h3> <p> <strong>AtomicExample.java</strong> </p> <pre> class Counter extends Thread { // Counter Variable int count = 0; //the method starts the execution of a thread public void run() { int max = 1; //increments the counter variable up to specified max time for (int i = 0; i <max; i++) { count++; } public class counter static void main(string args[]) throws interruptedexception creating an instance of the c="new" counter(); four threads thread t1="new" thread(c, 'first'); t2="new" 'second'); t3="new" 'third'); t4="new" 'fourth'); by calling start() method, we have started t1.start(); t2.start(); t3.start(); t4.start(); main will wait for all until execution do not complete t1.join(); t2.join(); t3.join(); t4.join(); prints final value count variable system.out.println(c.count); < pre> <p> <strong>Output:</strong> </p> <pre> 4 </pre> <h2>Synchronized Vs. Atomic Vs. Volatile</h2> <table class="table"> <tr> <th>Synchronized</th> <th>Atomic</th> <th>Volatile</th> </tr> <tr> <td>It applies to methods only.</td> <td>It applies to variables only.</td> <td>It also applies to variables only.</td> </tr> <tr> <td>It ensures visibility along with atomicity.</td> <td>It also ensures visibility along with atomicity.</td> <td>It ensures visibility, not atomicity.</td> </tr> <tr> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> <td>It stores in RAM, so accessing volatile variables is fast. But it does not provide thread-safety and synchronization.</td> </tr> <tr> <td>It can be implemented as a synchronized block or a synchronized method.</td> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> </tr> <tr> <td>It can lock the same class object or a different class object.</td> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> </tr> </table> <hr></max;></pre></max;>

Das obige Programm liefert die erwartete Ausgabe, wenn es in einer Single-Thread-Umgebung ausgeführt wird. Eine Multithread-Umgebung kann zu unerwarteten Ausgaben führen. Der Grund dafür ist, dass, wenn zwei oder mehr Threads gleichzeitig versuchen, den Wert zu aktualisieren, dieser möglicherweise nicht ordnungsgemäß aktualisiert wird.

Java-Angebote zwei Lösungen zur Lösung dieses Problems:

  • Durch die Verwendung von Sperre und Synchronisierung
  • Durch die Verwendung atomarer Variablen

Lassen Sie uns ein Java-Programm erstellen und eine atomare Variable verwenden, um das Problem zu lösen.

Durch die Verwendung einer Atomvariablen

AtomicExample.java

 class Counter extends Thread { // Counter Variable int count = 0; //the method starts the execution of a thread public void run() { int max = 1; //increments the counter variable up to specified max time for (int i = 0; i <max; i++) { count++; } public class counter static void main(string args[]) throws interruptedexception creating an instance of the c="new" counter(); four threads thread t1="new" thread(c, \'first\'); t2="new" \'second\'); t3="new" \'third\'); t4="new" \'fourth\'); by calling start() method, we have started t1.start(); t2.start(); t3.start(); t4.start(); main will wait for all until execution do not complete t1.join(); t2.join(); t3.join(); t4.join(); prints final value count variable system.out.println(c.count); < pre> <p> <strong>Output:</strong> </p> <pre> 4 </pre> <h2>Synchronized Vs. Atomic Vs. Volatile</h2> <table class="table"> <tr> <th>Synchronized</th> <th>Atomic</th> <th>Volatile</th> </tr> <tr> <td>It applies to methods only.</td> <td>It applies to variables only.</td> <td>It also applies to variables only.</td> </tr> <tr> <td>It ensures visibility along with atomicity.</td> <td>It also ensures visibility along with atomicity.</td> <td>It ensures visibility, not atomicity.</td> </tr> <tr> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> <td>It stores in RAM, so accessing volatile variables is fast. But it does not provide thread-safety and synchronization.</td> </tr> <tr> <td>It can be implemented as a synchronized block or a synchronized method.</td> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> </tr> <tr> <td>It can lock the same class object or a different class object.</td> <td>We can&apos;t achieve the same.</td> <td>We can&apos;t achieve the same.</td> </tr> </table> <hr></max;>

Synchronisiert vs. Atomar vs. Flüchtig

Synchronisiert Atomar Flüchtig
Dies gilt nur für Methoden. Dies gilt nur für Variablen. Dies gilt auch nur für Variablen.
Es sorgt für Sichtbarkeit und Atomizität. Es sorgt außerdem für Sichtbarkeit und Atomizität. Es sorgt für Sichtbarkeit, nicht für Atomizität.
Das können wir nicht erreichen. Das können wir nicht erreichen. Die Speicherung erfolgt im RAM, sodass der Zugriff auf flüchtige Variablen schnell erfolgt. Es bietet jedoch keine Thread-Sicherheit und Synchronisierung.
Es kann als synchronisierter Block oder synchronisierte Methode implementiert werden. Das können wir nicht erreichen. Das können wir nicht erreichen.
Es kann dasselbe Klassenobjekt oder ein anderes Klassenobjekt sperren. Das können wir nicht erreichen. Das können wir nicht erreichen.