CAS(Compare And Swap)
实现:一般实现实在循环里面进行无限CAS操作,我们也可以称之为自旋锁,但由此可以衍生出几个问题
问题一:ABA问题
问题二:CAS操作长期不成功带来的cpu资源消耗问题
更新基本类型类:AtomicBoolean,AtomicInteger,AtomicLong
更新数组类:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray
更新引用类型:AtomicReference,AtomicMarkableReference,AtomicStampedReference
原子更新字段类: AtomicReferenceFieldUpdater,AtomicIntegerFieldUpdater,AtomicLongFieldUpdater
其实上面各类原子变量使用方式大同小异,大家可以看源码的解释来自行使用,这里我选取几个来操作
先实现CAS自旋
/**
*类说明:实现CAS自旋锁
*/
public class HalfAtomicInt {
private static AtomicInteger atomicI = new AtomicInteger(0);
public static void increament() {
for (;;) {
int i = atomicI.get();
boolean suc = atomicI.compareAndSet(i, ++i);
if (suc) {
break;
}
}
}
public static void main(String[] args) {
for (int i=0;i<10;i++){
new Thread(new Runnable() {
@Override
public void run() {
for (int i=0;i<1000;i++) {
increament();
}
}
}).start();
}
SleepTools.second(3);
System.out.println(getCount());
}
public static int getCount() {
return atomicI.get();
}
}
输出
/**
*类说明:原子操作Integer类型
*/
public class UseAtomicInt {
static AtomicInteger ai = new AtomicInteger(10);
public static void main(String[] args) {
System.out.println(ai.getAndIncrement());//10--->11此次输出为10,输出后变为11,可以看作是ai++
System.out.println(ai.incrementAndGet());//11--->12此次输出为12,可以看作是++ai
for (int i=0;i<20;i++) {
new Thread(new Runnable() {
@Override
public void run() {
for (int i=0;i<100;i++){
ai.getAndIncrement();
}
}
}).start();
}
SleepTools.second(3);//这里睡眠是为了防止其他线程还没跑完就直接结束运行
System.out.println(ai.get());//会输出2012
}
}
控制台打印:
/**
*类说明:演示引用类型AtomicReference的原子操作类
*/
public class UseAtomicReference {
static AtomicReference<UserInfo> userRef = new AtomicReference<>();
public static void main(String[] args) {
UserInfo user = new UserInfo("ZhangSan", 29);//要修改的实体的实例
userRef.set(user);
UserInfo updateUser = new UserInfo("LiSi", 30);//要变化的新实例
userRef.compareAndSet(user, updateUser);
System.out.println(userRef.get().getName());
System.out.println(userRef.get().getAge());
System.out.println(user.getName());
System.out.println(user.getAge());
}
//定义一个实体类
static class UserInfo {
private 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;
}
}
}
打印:
/**
*类说明:演示带版本戳的AtomicStampedReference原子操作类
*/
public class UseAtomicStampedReference {
static AtomicStampedReference<String> asr =
new AtomicStampedReference<>("Ming",0);
public static void main(String[] args) throws InterruptedException {
final int oldStamp = asr.getStamp();//拿初始的版本号
final String oldReferenc = asr.getReference();
System.out.println(oldReferenc+"==========="+oldStamp);
Thread rightStampThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()
+"当前变量值:"+oldReferenc+"当前版本戳:"+oldStamp+"-"
+asr.compareAndSet(oldReferenc, oldReferenc+"Java",
oldStamp, oldStamp+1));
}
});
Thread errorStampThread = new Thread(new Runnable() {
@Override
public void run() {
String reference = asr.getReference();
System.out.println(Thread.currentThread().getName()
+"当前变量值:"+reference+"当前版本戳:"+asr.getStamp()+"-"
+asr.compareAndSet(reference, reference+"C",
oldStamp, oldStamp+1));
}
});
rightStampThread.start();
rightStampThread.join();
errorStampThread.start();
errorStampThread.join();
System.out.println(asr.getReference()+"==========="+asr.getStamp());
}
}
打印:
因篇幅问题不能全部显示,请点此查看更多更全内容