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