I have a AtomicInteger that is being incremented by multiple threads.
I want to reset to zero if that AtomicInteger overflows but in an atomic way. I want to make sure counter variable value is always positive so as soon as clientCounter overflow or going to overflow, I will reset that AtomicInteger to zero. I came up with below code but I am not sure is it thread safe because I am doing addition to check and reset. Is there any better way to do this?
private static final AtomicInteger clientCounter = new AtomicInteger(0);
// called by multiple threads
public static int getCounter() {
final int counter = clientCounter.incrementAndGet();
// reset "clientCounter" to zero as soon as it overflow
// basically I don't want "counter" value should be negative if it overflow
// is below thread safe?
if (counter + 1 < 0) {
clientCounter.set(0);
}
if (counter % SIZE == 0) {
// save counter in database
}
return counter;
}
Update:
Below is my method and I am using newCounter value to save in database as well. And the line where I am saving in database, it is asking to make newCounter as final variable and I can't make newCounter as final variable here. How to fix this now?
public static int getCounter() {
int counter;
int newCounter;
do {
counter = clientCounter.get();
newCounter = counter < Integer.MAX_VALUE ? counter + 1 : 1;
} while (!clientCounter.compareAndSet(counter, newCounter));
if (newCounter % SIZE == 0) {
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
// this is asking "newCounter" to make final
DBClient.getInstance().save(newCounter);
}
});
}
return newCounter;
}