Java JUC并发之原子引用

二十、原子引用

解决ABA问题 => 引入原子引用 对应思想:乐观锁

原子引用类 AtomicStampedReference<>(initialRef , initialStamp) 带版本号的原子操作!

AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1,1);

如果泛型是一个包装类,要注意对象的引用问题

注意:

Integer 使用了对象缓存机制,默认范围是 -128 - 127,超过范围会在堆中 new 一个新的对象;推荐使用静态工厂方法 valueOf获取对象实例,而不是 new!

因为 valueOf使用缓存,而 new 一定会创建新的对象,分配新的空间!

package com.liu.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

public class CASDemo {

    // CAS compareAndSet : 比较并交换

    public static void main(String[] args) {

        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1,1);

        new Thread(()->{
            int stamp = atomicStampedReference.getStamp(); // 获得版本号
            System.out.println("a1 ==> "  + stamp);


            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(atomicStampedReference.compareAndSet(1, 2,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1));

            System.out.println("a2 ==> "  + atomicStampedReference.getStamp());


            System.out.println(atomicStampedReference.compareAndSet(2, 1,
                    atomicStampedReference.getStamp(),
                    atomicStampedReference.getStamp() + 1));

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("a3 ==> "  + atomicStampedReference.getStamp());

        },"a").start();

        new Thread(()->{

            int stamp = atomicStampedReference.getStamp(); // 获得版本号
            System.out.println("b1 ==> "  + stamp);

            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(atomicStampedReference.compareAndSet(1, 6,
                    stamp,
                    stamp+1));
            System.out.println("b2 ==> "  + atomicStampedReference.getStamp());
        },"b").start();

    }
}

测试结果:
b2预期得到的版本号为 2,但实际上线程A中的修改操作让版本号变为了 3,线程B此时通过版本号检查发现线程A中出现了ABA问题,因此b2的CAS操作无法完成,返回了false。

posted @ 2021-07-17 23:57  夕立君  阅读(71)  评论(0编辑  收藏  举报