AtomicReference Usage
-
21-06-2021 - |
Question
Say you have the following class
public class AccessStatistics {
private final int noPages, noErrors;
public AccessStatistics(int noPages, int noErrors) {
this.noPages = noPages;
this.noErrors = noErrors;
}
public int getNoPages() { return noPages; }
public int getNoErrors() { return noErrors; }
}
and you execute the following code
private AtomicReference<AccessStatistics> stats =
new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));
public void incrementPageCount(boolean wasError) {
AccessStatistics prev, newValue;
do {
prev = stats.get();
int noPages = prev.getNoPages() + 1;
int noErrors = prev.getNoErrors;
if (wasError) {
noErrors++;
}
newValue = new AccessStatistics(noPages, noErrors);
} while (!stats.compareAndSet(prev, newValue));
}
In the last two lines
newValue = new AccessStatistics(noPages, noErrors);
while (!stats.compareAndSet(prev, newValue))
Does it means the new created AccessStatistics instance has same reference as the current AccessStatistics instance. how could it be ? Can Anyone explain it . Thanks a lot.
Solution
stats.compareAndSet(prev, newValue)
will fail and return false if the current reference held by stats
is not prev
.
Typically, in a multi-threaded environment, it is very possible that between prev = stats.get();
and stats.compareAndSet(prev, newValue);
another thread would have modified the reference held by stats
.
stats.compareAndSet(prev, newValue);
really says:
- if
stats
still holds a reference toprev
, as it was 5 lines before, update it to hold a reference tonewValue
- if however another thread has already changed the reference held by
stats
since I last checked 5 lines ago, discard my calculation and loop to recalculate a newnewValue
.
OTHER TIPS
The newly created object is, well, new. After the line that it is created, the only thing that refers to it is newValue
. Nothing else could -- how could it? The compareAndSet()
only sets if nothing else has in the meantime set it to some third value, besides the old one you know about prev
and the new one you made newValue
.