AtomicInteger in Java

Vandaag zullen we kijken naar AtomicInteger in Java. Atomic operations worden uitgevoerd als een enkele taakeenheid zonder interferentie van andere operaties. Atomic operations zijn noodzakelijk in een multi-threaded omgeving om inconsistentie in gegevens te voorkomen.

AtomicInteger

Laten we een eenvoudig multi-threaded programma maken waarbij elke thread de gedeelde count-variabele 4 keer verhoogt. Dus als er twee threads zijn, zou de waarde van count na hun afronding 8 moeten zijn. 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) {
        // verwerking van een taak
        try {
            Thread.sleep(i * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Als je het bovenstaande programma uitvoert, zul je merken dat de waarde van count varieert tussen 5, 6, 7, 8. De reden hiervoor is omdat count++ geen atomaire operatie is. Dus op het moment dat één thread de waarde leest en met één verhoogt, heeft een andere thread de oudere waarde gelezen, wat leidt tot een verkeerd resultaat. Om dit probleem op te lossen, moeten we ervoor zorgen dat de incrementoperatie op count atomair is. Dit kunnen we doen met behulp van Synchronisatie, maar Java 5 java.util.concurrent.atomic biedt wrapperklassen voor int en long die kunnen worden gebruikt om deze atomaire operatie te bereiken zonder het gebruik van Synchronisatie.

Voorbeeld van Java AtomicInteger

Hier is het bijgewerkte programma dat altijd de waarde van de teller als 8 zal weergeven omdat de methode incrementAndGet() van AtomicInteger de huidige waarde atomaire toeneemt met één.

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) {
        // verwerking van een taak
        try {
            Thread.sleep(i * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

Voordelen van het gebruik van Concurrency-klassen voor atomaire bewerkingen is dat we ons geen zorgen hoeven te maken over synchronisatie. Dit verbetert de leesbaarheid van de code en de kans op fouten wordt verminderd. Bovendien wordt aangenomen dat atomaire bewerkingen met Concurrency-klassen efficiënter zijn dan synchronisatie die het vergrendelen van bronnen inhoudt.

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