The getAndIncrement implementation of AtomicInteger - java

The getAndIncrement implementation of AtomicInteger does the following:
public final int getAndIncrement() {
for (;;) {
int current = get(); // Step 1 , get returns the volatile variable
int next = current + 1;
if (compareAndSet(current, next))
return current;
} }
Isn't it an equivalent of aVolatileVariable++? (which we know is not a correct usage). Without synchronization, how are we ensuring that this complete operation is atomic? What if the value of the volatile variable changes after the variable 'current' is read in Step 1?

The "secret sauce" is in this call:
compareAndSet(current, next)
The compareAndSet operation is going to fail (and return false) if the original volatile value has been changed concurrently after the read, forcing the code to continue with the loop.

Related

Java - Compare and Swap and synchronized Block

public class SimulatedCAS {
private int value;
public synchronized int get() { return value; }
public synchronized int compareAndSwap(int expectedValue, int newValue)
{
int oldValue = value;
if (oldValue == expectedValue)
value = newValue;
return oldValue;
}
}
public class CasCounter
{
private SimulatedCAS value;
public int getValue()
{
return value.get();
}
public int increment()
{
int value.get();
while (v != value.compareAndSwap(v, v + 1))
{
v = value.get();
}
}
}
I refereed a Book "Java Concurrency in Practice"
a Counter must be increased by multiple threads. I tried using the compare and swap method but at the end it make used of synchronized keyword which might again result in blocking and waiting of threads. using a synchronized block provides me the same performance can anybody state. what is the difference between using compare and swap and synchronized block ? or any other way to implement compare and swap without using synchronized block.
I need to increment counter with multiple threads
The AtomicInteger class is good for that.
You can create it with final AtomicInteger i=new AtomicInteger(initial_value); Then you can call i.set(new_value) to set its value, and you can call i.get() to get its value, and most importantly for your application, you can call i.incrementAndGet() to atomically increment the value.
If N different threads all call i.incrementAndGet() at "the same time," then
Each thread is guaranteed to see a different return value, and
The final value after they're all done is guaranteed to increase by exactly N.
The AtomicInteger class has quite a few other methods as well. Most of them make useful guarantees about what happens when multiple threads access the varaible.
Real Compare and Swap does optimistic locking. It changes value and then makes a rollback if something has changed the variable simultaneously. So, if the variable is modified rarely, then CAS performs better, than synchronized.
But if the variable is modified often, then synchronized performs better, because it doesn't allow anything to mess with the variable while it is changed. And so there's no need to make an expensive rollback.

Why is it possible to update atomic variables concurrently without race condition in Java?

The following code works without race condition
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(20);
IntStream.range(0, 1000)
.forEach(i -> executor.submit(atomicInt::incrementAndGet));
Here is the implementation of incrementAndGet
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
We can see current is not synchronized or locked, after one thread get the current another thread might already update the current.
But it seems like atomic class avoids race condition some how.
Can someone point out my mistake?
compareAndSet sets the value (and returns true) if and only if the first parameter is equal to the AtomicInteger's current value.
That is, if another thread had already changed the value, then current would not be equal to the current value, and the loop would run once more.
From the documentation of compareAndSet(int expect, int update):
Atomically sets the value to the given updated value if the current
value == the expected value.

Java spring multithreading atomic issue

I have a class
#Component
public class JmxConf implements Serializable {
private static final long serialVersionUID = 5586922486161726170L;
private AtomicInteger count = new AtomicInteger(0);
public AtomicInteger getCount() {
return count;
}
}
And I autowired this class to another
#Component
public class QueueListener {
private ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
#Autowired
private JmxConf jmxConf;
public doIt(){
if(jmxConf.getCount().get()>.....) {
jmxConf.getCount().incrementAndget();
......
executor.submit(new thread here);
jmxConf.getCount().decrementAndget();
}
}
}
We have one singleton bean which has a state but access to this state is controlled by an atomic variable. Will this class be thread-safe? And if not, why. Thanks
No it won't be atomic. You have a race here:
if(jmxConf.getCount().get()>.....) {
jmxConf.getCount().incrementAndget();
Imagine the scenario where the greater than is some number, just say 10.
if(jmxConf.getCount().get() > 10) {
jmxConf.getCount().incrementAndget();
What if, when the thread hits the if the value is 9. When it gets to the increment it was already incremented by another thread to 10 and now you increment it to a value of 11.
You should use compareAndSet.
while(true){
int value = jmxConf.getCount().get() + 1;
if(value > 10){
break;
}
if(mxConfg.getCount().compareAndSet(value-1, value){
executor.submit(new thread here);
jmxConf.getCount().decrementAndGet();
break;
}
}
You can read more on atomic references and compareAndSet offered by Java.
So why do we need the while(true)? The compareAndSet function takes two parameters
public final boolean compareAndSet(int expect, int update)
The method says "Try to update the AtomicInteger in a thread safe matter, here is the value I expect it to be currently and here is the value I want to update it with. If, when trying to do the update, the value of the AtomicInteger is what I expect than you can safely do the update. If it's not what I expect it to be then don't update it and notify me that you didn't update it."
Let's say we enter the if and the value is 5 if another thread is also trying to update the AtomicInteger with a value of 5 both threads will have an expectation of 5 as the parameter. Because it is thread-safe only one thread can win which means one will fail (the compareAndSet will return false on failure). In that case we should re-try the compareAndSet until we succeed or exceed the threshold in which we break.
AtomicInteger is thread-safe so this will be thread-safe.

whats the purpose of having infinite for loop in following code

Can somebody explain ....This is the official java AtomicBoolean getAndSet method's definition
public final boolean getAndSet(boolean newValue) {
for (;;) {
boolean current = get();
if (compareAndSet(current, newValue))
return current;
}
}
In Java 8, the sourcecode has been slightly restructured, making it easier to understand:
public final boolean getAndSet(boolean newValue) {
boolean prev;
do {
prev = get();
} while (!compareAndSet(prev, newValue));
return prev;
}
As you can see, compareAndSet, which returns a boolean, which comes from the native function Unsafe.compareAndSwapInt, might fail. In that case, the operation is simply repeated.
According to the documentation of Unsafe.compareAndSwapInt,
Atomically update Java variable to x if it is currently holding expected.
Returns:
true if successful
the function will fail if the value of the AtomicBoolean has been changed between calling get() and some point in Unsafe.compareAndSwapInt. This usually shouldn't be the case, but when it happens, it will poll the current value once again and hope the same thing doesn't repeat.
Clearly, it is not an infinite loop. The loop just has its exit condition inside the body:
return current;
In general, this is the typical idiom used in optimistic, lock-free atomic operations. A Compare-And-Swap (CAS) operation is retried until it succeeeds, and it will succeed as soon as it is not contended from another thread. More precisely, the exit condition is met whenever the return value of get() matches the current value as observed by compareAndSet(). It is very hard not to meet this condition, and it happens very rarely.

Are nested method calls of AtomicInteger also atomic in java

Would this operation be atomic or is there a chance of data race in between?
atomicInteger.set(-atomicInteger.get());
If there is a data race, how to negate an AtomicInteger atomically?
I would do it this way
public int getAndNegate(AtomicInteger i) {
for (;;) {
int current = i.get();
int next = -current;
if (i.compareAndSet(current, next))
return current;
}
}
No you need to synchronize to lock the instance I guess.
AtomicInteger has lots of methods to getAndSet but nothing to do inverse...
Apparently this was asked before on SO Does AtomicBoolean not have a negate() method? The solution on that page is interesting.
public final int getAndDecrement()
Atomically decrements by one the current value. Returns the previous value
AtomicInteger itsCounter = new AtomicInteger();
itsCounter.getAndDecrement();

Categories

Resources