What´s the difference between AtomicReference<Integer> vs. AtomicInteger?
Asked Answered
G

4

10

I don´t get the difference between these two:

AtomicReference<Integer> atomicReference = new AtomicReference<>(1);

vs.

AtomicInteger atomicInteger = new AtomicInteger(1);

Can someone generally say when to use AtomicReference? Hope someone can help me. Thanks.

Gearwheel answered 21/4, 2013 at 19:20 Comment(0)
T
13

A very important difference is that the methods compareAndSet and weakCompareAndSet have different semantics for AtomicReference<Integer> than they do for AtomicInteger. This is because with AtomicReference<Integer>, those methods use == for comparing and two Integer objects can be equal without being ==. With AtomicInteger, the comparison is of the integer value equality, not reference identity.

As others have pointed out, AtomicInteger has additional features not available with AtomicReference<Integer>. Also, AtomicInteger extends Number, so it inherits all the Number methods (doubleValue(), etc.) and can be used whenever a Number is expected.

Twopence answered 21/4, 2013 at 19:28 Comment(3)
Its worth pointing out also that auto-boxed Integer objects in the range -127 to 128 are interned and that their == will return true while Integers outside this range will not. Integers created with new Integer(3) will obviously not have the same identity though. This can cause all sorts of surprising behaviours.Barbbarba
@JedWesley-Smith - Excellent point. According to the API, values outside that range might also be cached. So to make matters worse the "surprising behaviours" may be different on different Java platforms.Twopence
Right, it is an undocumented hack that should not be relied upon.Barbbarba
M
8

Not much difference if you are using just set(...) and get() but the AtomicInteger has some other methods such as incrementAndGet() which only work for integers.

The AtomicReference wraps a volatile Object while AtomicInteger wraps a volatile int so it can do integer specific methods including increment, decrement, and add methods. AtomicInteger also extends Number which means it supports doubleValue(), longValue(), etc. methods.

Mineralogy answered 21/4, 2013 at 19:21 Comment(0)
H
6

AtomicReference is a generic class that can refer to arbitrary types.
If you want to use an instance of your own class atomically, you need AtomicReference<V>.

AtomicInteger is a specialized version that contains integers. It is more efficient (no unnecessary boxing), and has useful methods like incrementAndGet().

Harmaning answered 21/4, 2013 at 19:21 Comment(1)
Also, two Integer objects can be equal without being identical.Twopence
D
2

As pointed out by others, AtomicReference<Integer> uses == to compare objects. Therefore,compareAndSet(expect, update) will update your initial reference only if expect equals to the object stored in your your atomic reference using ==.

It can lead to some tricky bugs if you use AtomicReference for numeric types, i.e. Integer or Long. Please note that static constructors of those classes (for example, Integer.valueOf(int value)) return internally cached objects for small values. In other words, two different calls to Integer.valueOf(5) returns the same instance of Integer. It is safe, as the classes are immutable. In the result, if you use AtomicReference<Integer> whereas you should really be using AtomicInteger, it may work fine for these small numbers, because == may actually compare the same objects. It gets worse only when you begin to handle with higher values at some point.

Summing up, using AtomicInteger is much safer for numeric operations :)

Darnall answered 21/4, 2013 at 20:24 Comment(2)
See comment on Ted Hopp's answer, the interning of the Integer objects only happens for a restricted set, not for all. Relying on the interning to make == work is considered harmful as it is undocumented and may change.Barbbarba
Well, that is what I meant by "small values". I did not want to specify the range, as it may be a subject to change. My conclusion was exactly what you are saying: you should never rely on == to work for numeric objects.Darnall

© 2022 - 2024 — McMap. All rights reserved.