原子操作和实现
Atomic
基于循环和CAS实现,特点线程不阻塞,适合并发冲突少的场景。 对于普通的Atomic类本文不在描述,实现较为简单。
AtomicMarkableReference
解决了ABA问题,只关心有没有改过
AtomicStampedReference
解决了ABA问题,不仅关心有没有改过,还关心被改过几次 示例:
public class UseAtomicStampedReference {
static AtomicStampedReference<String> asr
= new AtomicStampedReference("mark",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() {
System.out.println(Thread.currentThread().getName()+":当前变量值:"
+oldReference + "-当前版本戳:" + oldStamp + "-"
+ asr.compareAndSet(oldReference,
oldReference + "+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());
}
}
// 结果
mark============0
Thread-0:当前变量值:mark-当前版本戳:0-true
Thread-1:当前变量值:mark+Java-当前版本戳:1-false
mark+Java============1
扩展
LongAdder
写热点分散,不能保证强一致,只是近似值。
问题
ABA问题
这种问题大部分业务场景,如count++操作是没有影响的,但一定要知道这个问题。
衍生:订单下的ABA问题
循环时间长开销大
循环时间长,竞争激烈,它的效率就比synchronized低了(synchronized只有在竞争极小情况下才会采用偏向和轻量级锁)。