AtomicStampedReference prevents A == > B ==> A
AtomicReference allows a reference to an object to be atomically updated.
The object used should be immutable.
It is used when you want to update more than one field atomically. You wrap the fields in an Immutable object and use AtomicReference to update the reference to it.
AtomicStampedReference is similar to AtomicReference except it also has an int called initialStamp. The purpose of the initialStamp is to prevent the situation where immutable object being referenced goes from A to B and back to A again. The idea is you pass a unique value as the initialStamp. If the reference to the immutable object is the same but the initialStamp is different this suggests that A ==> B ==> A occurred. When A ==> B ==> A occurs the atomic update will fail and it will attempt to do the CAS operation again.
To get the code for this example:
git clone https://github.com/spotadev/java-examples.git
In src/main/java navigate to this package:
com.javaspeak.java_examples.concurrency.cas.atomicStampedReference
You can run the code from the main method of:
AtomicStampedReferenceUpdater
package com.javaspeak.java_examples.concurrency.cas.atomicStampedReference;
import java.util.concurrent.atomic.AtomicStampedReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author John Dickerson - 7 Dec 2022
*/
public class AtomicStampedReferenceUpdater {
private static Logger logger = LoggerFactory.getLogger( AtomicStampedReferenceUpdater.class );
private Long time = Long.decode( "1" );
private AtomicStampedReference<Long> atomicStampedReference =
new AtomicStampedReference<Long>( time, 1 );
public Long setTime( Long time ) {
int[] oldStamp = new int[1];
while ( true ) {
Long oldTime = atomicStampedReference.get( oldStamp );
int newStamp = oldStamp[0] + 1;
if ( atomicStampedReference.compareAndSet( oldTime, time, oldStamp[0], newStamp ) ) {
return oldTime;
}
}
}
public Long getTime( int[] updatedStamp ) {
int[] stamp = new int[1];
Long time = atomicStampedReference.get( stamp );
updatedStamp[0] = stamp[0];
return time;
}
public static void main( String[] args ) {
AtomicStampedReferenceUpdater atomicStampedReferenceUpdater =
new AtomicStampedReferenceUpdater();
Long oldTime = atomicStampedReferenceUpdater.setTime( Long.valueOf( 1000 ) );
logger.info( "oldTime = " + oldTime );
int[] version = new int[1];
Long newTime = atomicStampedReferenceUpdater.getTime( version );
logger.info( "newTime = " + newTime + ", version: " + version[0] );
}
}
Back: Atomic Classes | Concurrency
Page Author: JD