AtomicInteger to generate a limited sequence

How can we use AtomicInteger to generate a limited sequence, say that the sequence number should be from 1 to 60. After the sequence reaches 60, it should start again with 1. I wrote this code, although I'm not quite sure what it is thread safe or not?

public int getNextValue() { int v; do { v = val.get(); if ( v == 60) { val.set(1); } } while (!val.compareAndSet(v , v + 1)); return v + 1; } 
+7
java atomic
source share
6 answers

You could do

 return val.getAndIncrement() % 60; 

If you are not worried about exceeding the integer maximum value (2147483647). If this is a concern, you can take a look at the implementation of getAndIncrement :

 public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) return current; } } 

All you need to change is an int next... for something like:

 int next = (current + 1) % 60; 

Unfortunately. This goes through 0-> 59. You needed 1-> 60, so add one to the return value to get the desired result.

+14
source share

You can do this on one line using Java 8.

 AtomicInteger counter = new AtomicInteger(); public int getNextValue() { return counter.updateAndGet(n -> (n >= 60) ? 1 : n + 1); } 
+3
source share

If you make the method synchronized , then it will be thread safe until val is nowhere else available. The approach, however, is a bit cumbersome; I would rewrite it as follows:

 public synchronized int getNextValue() { val.compareAndSet(60, 0); // Set to 0 if current value is 60. return val.incrementAndGet(); } 

This gives 1 to 60 seconds inclusive . If you really need 1 to 59, replace 60 with 59 .

+1
source share

No, this is not thread safe - you should not call set inside the loop:

 int value, next; do { value = val.get(); next = (value == 60) ? 1 : (value + 1); } while (!val.compareAndSet(value, next); return next; 
0
source share

Any specific reason to use AtomicInteger here, and not just a simple synchronized method?

How about something simple:

 private int val=1; public synchronized int getNextValue() { int v=val; val = (val==60) ? 1 : (val+1); return v; } 
0
source share

Fast response, not thread safe. The test and set must be atomic, unless you synchronize the whole method. Pay attention to val.get (), and checking v is not atomic. If the stream is issued after v = val.get (), you will receive two calls with the same sequence number.

Also, if compareAndSet fails, you never change the value, it will be an infinite loop.

AtomicInteger has a getAndIncrement () call. This will give you the net return value.

Gliding is a little trickier. One solution is to change the return value. Something like that:

 int v = val.getAndIncrement(); return (v % 60) + 1; 

Since each thread has a local copy of v, we can safely do some math and return a value. If you get overflow, there is one sticking point. Depending on how often you generate the sequence number, this may or may not be a problem.

0
source share

All Articles