Я изучаю пакет java.util.concurrent.atomic
и пробую свои силы на Atomic Integer
.Насколько я понимаю, пакет Atomic помогает писать код без блокировки, а не синхронизированный блок.Поэтому, чтобы проверить мое понимание, я написал следующий код:
public class Test{
private final AtomicInteger ai;
public void increment() {
int oldVal = ai.get();
while(!ai.compareAndSet(oldVal, oldVal+1)) {
oldVal = ai.get();
}
}
public int incrementModified() {
return ai.incrementAndGet();
}
public int get() {
return ai.get();
}
public static void main(String[] args) {
Test pc = new Test(5);
Runnable r1 = () -> {
pc.increment();
};
Runnable r2 = () -> {
pc.increment();
};
Runnable r3 = () -> {
pc.increment();
};
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);
t1.start();
t2.start();
t3.start();
System.out.println(pc.get());
}
Когда я выполняю приведенный выше код, я ожидаю, что результат будет 8 , но я получаю вывод как 7 /8 .Затем я даже использовал встроенный метод incrementAndGet()
и по-прежнему получал один и тот же вывод после запуска программы несколько раз.
Насколько я понимаю, поскольку атомарный можно использовать в качестве альтернативы синхронизированному блоку, и он делаетинкрементные операции приращения с использованием CAS (сравнить и установить инструкцию), я всегда должен получать выходные данные как 8.
Но так как я получаю различные выходные данные, я предполагаю, что существует гонка, и, таким образом, o / p изменяется между 7/8.
Может ли кто-нибудь указать на ошибки, которые я совершаю в приведенном выше коде, или исправить мои представления об атомарных классах в Java?
РЕДАКТИРОВАТЬ:
Как отмечено в комментариях, я не использовал join()
и, таким образом, получал неверный результат, поскольку основной поток запрашивал значение, в то время как какой-то поток все еще находился в середине операции.Я добавил его, и после нескольких тестирований я могу увидеть ожидаемый результат.