The other answers addressed why AtomicInteger
is needed. I'd like to clarify what that document is talking about.
The use of the term atomic in that document isn't for the same purpose as its use in AtomicInteger
.
That document also states
Atomic actions cannot be interleaved, so they can be used without fear
of thread interference.
This refers to
int x;
x = 1; // thread 1
x = 2; // thread 2
System.out.println(x); // thread 3
thread 3
is guaranteed to see either the value 1
or the value 2
.
However, with long
or double
, you don't have that guarantee. The Java Language Specification states
For the purposes of the Java programming language memory model, a
single write to a non-volatile long
or double
value is treated as two
separate writes: one to each 32-bit half. This can result in a
situation where a thread sees the first 32 bits of a 64-bit value from
one write, and the second 32 bits from another write.
So, for example,
long x;
x = 0xffff_ffffL; // thread 1
x = 0x7fff_ffff_0000_0000L; // thread 2
System.out.println(x); // thread 3
thread 3
is allowed to see the first 32 bits from thread 1
's assignment and the last 32 bits from thread 2
's assignment, creating the long
value 7fff_ffff_ffff_ffff
. The same can occur for double
.
Modifying your long
or double
variable with volatile
prevents this behavior.