原子类

image.png
我们可以看到这些getAndAdd这种复杂类型,底层也是运行while true,cas方式来运行
image.png

AtomicReference

  1. public class Test32 {
  2. public static void main(String[] args) {
  3. DecimalAccountCas decimalAccountCas = new DecimalAccountCas(new BigDecimal("10000"));
  4. DecimalAccount.demo(decimalAccountCas);
  5. }
  6. }
  7. class DecimalAccountCas implements DecimalAccount{
  8. private AtomicReference<BigDecimal> balance;
  9. public DecimalAccountCas(BigDecimal balance) {
  10. this.balance = new AtomicReference<>(balance);
  11. }
  12. @Override
  13. public BigDecimal getBalance() {
  14. return balance.get();
  15. }
  16. @Override
  17. public void withdraw(BigDecimal amount) {
  18. while (true){
  19. BigDecimal prev = balance.get();
  20. BigDecimal next = prev.subtract(amount);
  21. if (balance.compareAndSet(prev,next)) {
  22. break;
  23. }
  24. }
  25. }
  26. }
  27. interface DecimalAccount{
  28. BigDecimal getBalance();
  29. void withdraw(BigDecimal amount);
  30. static void demo(DecimalAccount account){
  31. List<Thread> ts = new ArrayList<>();
  32. long start = System.nanoTime();
  33. for (int i = 0;i<1000;i++){
  34. ts.add(new Thread(()->{
  35. account.withdraw(new BigDecimal("10.00"));
  36. }));
  37. }
  38. ts.forEach(Thread::start);
  39. ts.forEach(t->{
  40. try{
  41. t.join();
  42. }catch (Exception e){
  43. e.printStackTrace();
  44. }
  45. });
  46. long end = System.nanoTime();
  47. System.out.println(account.getBalance() + "cost : " + ((end-start)/1000_000) +" ms");
  48. }
  49. }

ABA问题

image.png
这边修改时,并没有感知。所以需要加上版本号

ABA问题解决

  1. static AtomicStampedReference<String> ref = new AtomicStampedReference<>("A",0);
  2. public static void main(String[] args) {
  3. String s = ref.getReference();
  4. int stamp = ref.getStamp();
  5. other();
  6. try {
  7. TimeUnit.SECONDS.sleep(1);
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }
  11. boolean c = ref.compareAndSet(s, "C",stamp,stamp+1);
  12. System.out.println(c);
  13. }
  14. public static void other(){
  15. new Thread(()->{
  16. String reference = ref.getReference();
  17. int stamp = ref.getStamp();
  18. System.out.println(ref.compareAndSet(reference, "B",stamp,stamp+1));
  19. }).start();
  20. try {
  21. Thread.sleep(500);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. new Thread(()->{
  26. String reference = ref.getReference();
  27. int stamp = ref.getStamp();
  28. System.out.println(ref.compareAndSet(reference, "A",stamp,stamp+1));
  29. }).start();
  30. }