原子类
我们可以看到这些getAndAdd这种复杂类型,底层也是运行while true,cas方式来运行
AtomicReference
public class Test32 {
public static void main(String[] args) {
DecimalAccountCas decimalAccountCas = new DecimalAccountCas(new BigDecimal("10000"));
DecimalAccount.demo(decimalAccountCas);
}
}
class DecimalAccountCas implements DecimalAccount{
private AtomicReference<BigDecimal> balance;
public DecimalAccountCas(BigDecimal balance) {
this.balance = new AtomicReference<>(balance);
}
@Override
public BigDecimal getBalance() {
return balance.get();
}
@Override
public void withdraw(BigDecimal amount) {
while (true){
BigDecimal prev = balance.get();
BigDecimal next = prev.subtract(amount);
if (balance.compareAndSet(prev,next)) {
break;
}
}
}
}
interface DecimalAccount{
BigDecimal getBalance();
void withdraw(BigDecimal amount);
static void demo(DecimalAccount account){
List<Thread> ts = new ArrayList<>();
long start = System.nanoTime();
for (int i = 0;i<1000;i++){
ts.add(new Thread(()->{
account.withdraw(new BigDecimal("10.00"));
}));
}
ts.forEach(Thread::start);
ts.forEach(t->{
try{
t.join();
}catch (Exception e){
e.printStackTrace();
}
});
long end = System.nanoTime();
System.out.println(account.getBalance() + "cost : " + ((end-start)/1000_000) +" ms");
}
}
ABA问题
ABA问题解决
static AtomicStampedReference<String> ref = new AtomicStampedReference<>("A",0);
public static void main(String[] args) {
String s = ref.getReference();
int stamp = ref.getStamp();
other();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
boolean c = ref.compareAndSet(s, "C",stamp,stamp+1);
System.out.println(c);
}
public static void other(){
new Thread(()->{
String reference = ref.getReference();
int stamp = ref.getStamp();
System.out.println(ref.compareAndSet(reference, "B",stamp,stamp+1));
}).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
String reference = ref.getReference();
int stamp = ref.getStamp();
System.out.println(ref.compareAndSet(reference, "A",stamp,stamp+1));
}).start();
}