Атомарные типы в Java
Пакет java.util.concurrent.atomic дает
счетчики и ссылки, у которых отдельные операции
выполняются атомарно на уровне процессора. Для
одного числа часто хватает AtomicInteger
без synchronized.
Метод incrementAndGet() прибавляет единицу
и возвращает новое значение. addAndGet(int delta)
увеличивает на заданный шаг. Чтение через
get() тоже атомарно.
Два потока по тысяче приращений без явного замка:
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
private static final AtomicInteger hits = new AtomicInteger();
public static void main(String[] args) throws InterruptedException {
Runnable step = () -> {
for (int i = 0; i < 1000; i++) {
hits.incrementAndGet();
}
};
Thread left = new Thread(step);
Thread right = new Thread(step);
left.start();
right.start();
left.join();
right.join();
System.out.println(hits.get());
}
}
Для условного обновления есть compareAndSet(expected, update):
запись проходит только если текущее значение совпало
с ожидаемым:
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) {
AtomicInteger slot = new AtomicInteger(5);
boolean swapped = slot.compareAndSet(5, 9);
System.out.println(swapped);
System.out.println(slot.get());
}
}
Атомарные типы не заменяют замок, когда нужно согласованно менять несколько полей. Для одного счетчика или флага они короче и обычно быстрее тяжелого монитора.
AtomicInteger visits. Три
потока по 150 вызовов
incrementAndGet(). После join
выведите 450.