Lets say I'm interacting with a system that has two incrementing counters which depend on each other (these counters will never decrement): int totalFoos; // barredFoos plus nonBarredFoos int barredFoos;
I also have two methods: int getTotalFoos(); // Basically a network call to localhost int getBarredFoos(); // Basically a network call to localhost
These two counters are kept and incremented by code that I don't have access to. Let's assume that it increments both counters on an alternate thread but in a thread-safe manner (i.e. at any given point in time the two counters will be in sync).
What is the best way to get an accurate count of both barredFoos and nonBarredFoos at a single point in time?
The completely naive implementation:
int totalFoos = getTotalFoos();
int barredFoos = getBarredFoos();
int nonBarredFoos = totalFoos - barredFoos;
This has the issue that the system could increment both counters in between the two method calls and then my two copies would be out of sync and barredFoos
would have a value of more than it did when totalFoos
was fetched.
Basic double-checked implementation:
while (true) {
int totalFoos = getTotalFoos();
int barredFoos = getBarredFoos();
if (totalFoos == getTotalFoos()) {
// totalFoos did not change during fetch of barredFoos, so barredFoos should be accurate.
int nonBarredFoos = totalFoos - barredFoos;
break;
}
// totalFoos changed during fetch of barredFoos, try again
}
This should work in theory, but I'm not sure that the JVM guarantees that this is what actually happens in practice once optimization and such is taken into account. For an example of these concerns, see http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html (Link via Romain Muller).
Given the methods I have and the assumption above that the counters are in fact updated together, is there a way I can guarantee that my copies of the two counts are in sync?