3

I was reading some documents about Atomic variables in Java. As written everywhere, AtomicInteger is supposed to be thread-safe.

As per my understanding of atomic integers, it works on the principle of Compare and Swap algorithm. I am unable to understand how will this work in case, when two threads try to increment the same atomic variable a exactly same time.

say I have define AtomicInteger var = 1, and this is being used by two threads Thread_1 and Thread_2. What will happen when both the thread will try to increment the var at the same time T1. I know this will be rare situation, but what if it happens. In compare and swap, it reads and updates the variable in a single atomic operation and it checks value from memory. so what if at time T1-1, value of var is 5 and both Thread1 and Thread2 will start incrementing it? Which one will fail? Will it be random behaviour? or I am missing something very basic.

Geek_To_Learn
  • 1,816
  • 5
  • 28
  • 48
  • 1
    "I know this will be rare" The rarity entirely depends on the situation. It is common enough that `LongAdder` was provided in Java 8 to provide a less contended way to increment a long in multiple threads than `AtomicLong`. – Andy Turner May 20 '19 at 16:11

3 Answers3

8

Compare and swap is atomic at the CPU level.

You can implement an increment operation explicitly with compare and swap:

int value;
do { 
  value = var.get();
} while (!var.compareAndSwap(value, value + 1));

The compareAndSwap is guaranteed by the CPU to be atomic (there will be a native implementation of this).

If two threads hit this compareAndSwap at the same time, only one of them will "win", receiving true as the result of the compareAndSwap call, so the loop stops.

The other thread will "lose", and receive false as the result, and so will go round the loop again: it reads a new value, and then tries the CAS again. If this succeeds (because either no other thread was trying to do it at the same time, or it "won" over another thread), the loop stops; otherwise, it just tries again.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • does the "compareAndSetLong()" operation at the JNI level only be guaranteed to be run by one thread at a time? so two threads cannot access "compareAndSetLong()" at the same time? – user2606235 Jan 22 '23 at 11:56
  • @user2606235 "so two threads cannot access "compareAndSetLong()" at the same time" correct. – Andy Turner Jan 23 '23 at 08:54
3

so what if at time T1-1, value of var is 5 and both Thread1 and Thread2 will start incrementing it?

One of them will successfully execute compare ans swap with current value of 5 and new value of 6, the other will fail and try again with value of 6 and new value of 7. They can't both succeed with current value of 5 and new value of 6, it's handled at the CPU level.

Even if they run at different cores and the CAS operation is executed at exactly the same time, still one of the operations will fail, which one is effectively random(might not be depending on the CPU implementation).

Oleg
  • 6,124
  • 2
  • 23
  • 40
  • I am not able to understand how this will work in multi-core system> – Geek_To_Learn May 20 '19 at 08:47
  • This is just something the CPU does, treat it as a black box. You need to learn about CPU architecture(start by reading https://www.amazon.com/Computer-Architecture-Quantitative-John-Hennessy/dp/012383872X) if you want to understand how exactly it's done. – Oleg May 20 '19 at 09:14
2

It is a typical race condition situation. Consider this increment operation as a small room with a small door, where only one person can fit and perform some operations. The first thread of two who manages to enter this room will perform the increment operation. Then when it finishes, the second= "less lucky" thread will do its job. But essential thing is that the result of both operations is consistent in terms that they don't perform increment operations in parallel.

Andremoniy
  • 34,031
  • 20
  • 135
  • 241