AtomicInteger in Java

Heute werden wir uns AtomicInteger in Java ansehen. Atomare Operationen werden in einer einzelnen Einheit von Aufgaben ohne Einmischung anderer Operationen durchgeführt. Atomare Operationen sind in einer mehrfädigen Umgebung notwendig, um Dateninkonsistenzen zu vermeiden.

AtomicInteger

Lassen Sie uns ein einfaches mehrfädiges Programm erstellen, bei dem jeder Thread die gemeinsame count-Variable 4 Mal erhöht. Wenn es also zwei Threads gibt, sollte der Wert von count nach ihrem Abschluss 8 sein. JavaAtomic.java

package com.journaldev.concurrency;

public class JavaAtomic {

    public static void main(String[] args) throws InterruptedException {

        ProcessingThread pt = new ProcessingThread();
        Thread t1 = new Thread(pt, "t1");
        t1.start();
        Thread t2 = new Thread(pt, "t2");
        t2.start();
        t1.join();
        t2.join();
        System.out.println("Processing count=" + pt.getCount());
    }

}

class ProcessingThread implements Runnable {
    private int count;

    @Override
    public void run() {
        for (int i = 1; i < 5; i++) {
            processSomething(i);
            count++;
        }
    }

    public int getCount() {
        return this.count;
    }

    private void processSomething(int i) {
        // Verarbeitung einer bestimmten Aufgabe
        try {
            Thread.sleep(i * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Wenn Sie das obige Programm ausführen, werden Sie feststellen, dass der Wert von count zwischen 5, 6, 7, 8 variiert. Der Grund dafür ist, dass count++ keine atomare Operation ist. Wenn also ein Thread seinen Wert liest und um eins erhöht, hat ein anderer Thread den älteren Wert gelesen, was zu einem falschen Ergebnis führt. Um dieses Problem zu lösen, müssen wir sicherstellen, dass die Inkrementoperation auf count atomar ist. Dies können wir durch Synchronisation erreichen, aber Java 5 java.util.concurrent.atomic bietet Wrapper-Klassen für int und long, die verwendet werden können, um diese atomare Operation ohne Verwendung von Synchronisation zu erreichen.

Java AtomicInteger Beispiel

Hier ist das aktualisierte Programm, das immer den Wert „8“ ausgeben wird, weil die Methode incrementAndGet() von AtomicInteger den aktuellen Wert atomar um eins erhöht.

package com.journaldev.concurrency;

import java.util.concurrent.atomic.AtomicInteger;

public class JavaAtomic {

    public static void main(String[] args) throws InterruptedException {

        ProcessingThread pt = new ProcessingThread();
        Thread t1 = new Thread(pt, "t1");
        t1.start();
        Thread t2 = new Thread(pt, "t2");
        t2.start();
        t1.join();
        t2.join();
        System.out.println("Processing count=" + pt.getCount());
    }
}

class ProcessingThread implements Runnable {
    private AtomicInteger count = new AtomicInteger();

    @Override
    public void run() {
        for (int i = 1; i < 5; i++) {
            processSomething(i);
            count.incrementAndGet();
        }
    }

    public int getCount() {
        return this.count.get();
    }

    private void processSomething(int i) {
        // Verarbeitung eines Jobs
        try {
            Thread.sleep(i * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Vorteile der Verwendung von Concurrency-Klassen für atomare Operationen sind, dass wir uns nicht um Synchronisation kümmern müssen. Dies verbessert die Lesbarkeit des Codes und reduziert die Fehleranfälligkeit. Außerdem werden atomare Operationen in Concurrency-Klassen als effizienter angesehen als Synchronisation, die das Sperren von Ressourcen beinhaltet.

Source:
https://www.digitalocean.com/community/tutorials/atomicinteger-java