如题两个类均为原子操作,是线程安全的
对于ABA的问题,由于普通的CAS在进行比较的时候是拿一个值和期望值进行比较是否一样,如果一样的话会做替换复制操作,不一样不会进行替换赋值操作。但是在使用中如果一个值被多个线程更改由A变成B在由B变成A,如果单纯去比较值的话CAS是可以通过的,但是对于一些的含有过程的业务场景来说这个是有问题,所以可以使用AtomicStampedReference来处理,它在处理的过程中不仅会比较值还会比较时间戳,这样就保证了真正的唯一相符。
eg:当用户低于20是进行充值,但是用户最多只能充值两次,
public class ThreadAtomicStampedReference {
static AtomicStampedReference<Integer> money = new AtomicStampedReference<Integer>(19,0);
final static AtomicInteger at = new AtomicInteger(0);
public static void main(String[] args) {
for(int i=0;i<3;i++){
final Integer stamp=money.getStamp();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
Integer m = money.getReference();
Integer stamp=money.getStamp();
if(m<20&&at.get()<2){
if(money.compareAndSet(m,m+20,stamp,stamp+1)){
System.out.println("余额小于20,充值成功,当前余额:"+money.getReference());
at.getAndIncrement();
}
}
}
}
}).start();
}
new Thread(new Runnable() {
@Override
public void run() {
while(true){
Integer m = money.getReference();
Integer stamp = money.getStamp();
if(m>10){
System.out.println("金额大于10:"+m);
if(money.compareAndSet(m,m-10,stamp,stamp+1)){
System.out.println("成功消费10元,剩余金额:"+money.getReference());
}
}else {
System.out.println("余额不足10元");
}
}
}
}).start();
}
}
余额小于20,充值成功,当前余额:39
金额大于10:39
成功消费10元,剩余金额:29
金额大于10:29
成功消费10元,剩余金额:19
余额小于20,充值成功,当前余额:39
金额大于10:39
成功消费10元,剩余金额:29
金额大于10:29
成功消费10元,剩余金额:19
金额大于10:19
成功消费10元,剩余金额:9
余额不足10元
余额不足10元
余额不足10元
余额不足10元
余额不足10元
余额不足10元
余额不足10元
余额不足10元
余额不足10元
余额不足10元
余额不足10元