/**
* 类说明:演示引用类型的原子操作类
*/
public class UseAtomicReference {
static AtomicReference<UserInfo> atomicUserRef;
public static void main(String[] args) {
UserInfo user = new UserInfo("Mark", 15);//要修改的实体的实例
atomicUserRef = new AtomicReference(user);
UserInfo updateUser = new UserInfo("Bill", 17);
boolean a = atomicUserRef.compareAndSet(user, updateUser);
System.out.println(a);
System.out.println(atomicUserRef.get());
System.out.println(user);
}
//定义一个实体类
static class UserInfo {
private volatile String name;
private int age;
public UserInfo(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "UserInfo{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
}
Note:
atomicUserRef.compareAndSet (user, updateUser); the object is to change the original path of the reference, but the value itself does not change
new AtomicReference (user); encapsulating the object, so as to become an atomic operation
AtomicStampedReference
create
AtomicStampedReference<String> asr=new AtomicStampedReference("djy",0);
Source code for:
Note:
Here you can see the so-called ABA AtomicStampedReference able to solve the problem, a very simple version control
ABA problem solving
/**
* 类说明:演示带版本戳的原子操作类
*/
public class UseAtomicStampedReference {
static AtomicStampedReference<String> asr
= new AtomicStampedReference("djy", 0);
public static void main(String[] args) throws InterruptedException {
//拿到当前的版本号(旧)
final int oldStamp = asr.getStamp();
final String oldReference = asr.getReference();
System.out.println(oldReference + "============" + oldStamp);
Thread rightStampThread = new Thread(new Runnable() {
@Override
public void run() {
asr.compareAndSet(oldReference, "java", oldStamp, oldStamp + 1);
}
});
Thread errorStampThread = new Thread(new Runnable() {
@Override
public void run() {
String reference = asr.getReference();
int stamp = asr.getStamp();
asr.compareAndSet(reference, "C++", stamp, stamp + 1);
}
});
rightStampThread.start();
//让线程充分运行完毕
rightStampThread.join();
errorStampThread.start();
errorStampThread.join();
System.out.println(asr.getReference() + "============" + asr.getStamp());
}
}
AtomicMarkableReference
Usage and consistent AtomicStampedReference
The difference AtomicMarkableReference and AtomicStampedReference?
AtomicStampedReference
Constructor initialStamp (timestamp) to uniquely identify a reference variable, in the internal structure, a instantiates a Pair objects, Pair object recording time stamp information and the object references used int as a time stamp, when in actual use, to the only guarantee a time stamp (usually made from growing), if the time stamp if repeated, will appear ABA problem.
The AtomicStampedReference each reference variables are put pair.stamp this time stamp, so that you can solve the problem of CAS in the ABA.
/**
* Creates a new {@code AtomicStampedReference} with the given
* initial values.
*
* @param initialRef the initial reference
* @param initialStamp the initial stamp
*/
public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
}
AtomicMarkableReference
AtomicStampedReference know, reference variables have been changed several times midway. Sometimes, we do not care about reference variables changed several times, but simply concerned about whether or not changed , so there AtomicMarkableReference.
The only difference AtomicMarkableReference is no longer used int identity reference, but the use of boolean variable - Indicates whether the reference variable is changed.
Constructor
/**
* Creates a new {@code AtomicMarkableReference} with the given
* initial values.
*
* @param initialRef the initial reference
* @param initialMark the initial mark
*/
public AtomicMarkableReference(V initialRef, boolean initialMark) {
pair = Pair.of(initialRef, initialMark);
}