CAS你知道吗?原子类AtomicInteger的ABA问题谈谈…

2019-10-12 08:29:33来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

CAS你知道吗?原子类AtomicInteger的ABA问题谈谈?

(1)CAS是什么?

       比较并交换

     举例1,  CAS产生场景代码?

import java.util.concurrent.atomic.AtomicInteger;

public class CASDemo {
    public static void main(String[] args) {
        AtomicInteger atomicInteger=new AtomicInteger(5);//主物理内存
        //比较5
        System.out.println(atomicInteger.compareAndSet(5, 2019)+"\t current data(主物理内存) : "+ atomicInteger.get());
        //修改失败
        System.out.println(atomicInteger.compareAndSet(5, 1024)+"\t current data(主物理内存) : "+ atomicInteger.get());
    }
}

   举例2,  CAS产生场景代码?原子引用

public class CAS_ABADemo {
    public static void main(String[] args) {

        //========================原子引用==========================
        User A = new User("A", 123);
        User B = new User("B", 456);
        //主物理内存 引用比较的是地址
        AtomicReference<User> atomicReference1 = new AtomicReference<>();
        atomicReference1.set(A);
        System.out.println(atomicReference1.compareAndSet(A, B) + "\t" + atomicReference1.get().toString());
        System.out.println(atomicReference1.compareAndSet(A, B) + "\t" + atomicReference1.get().toString());
    }
}
class User {
    String name;
    int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
原子引用

   参考博客:CopyOnWriteArrayList  写时复制----------https://www.cnblogs.com/huangjuncong/p/9160713.html

   参考博客:ReentrantLock 独占锁(可重入锁)----------https://www.cnblogs.com/takumicx/p/9338983.html

举例3,ABA问题的产生和解决方案代码场景。

public class ABADemo {
    static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
    static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);
    public static void main(String[] args) {
        System.out.println("======ABA问题的产生======");

        new Thread(() -> {
            atomicReference.compareAndSet(100, 101);
            atomicReference.compareAndSet(101, 100);
        }, "t1").start();

        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();

            }
            System.out.println(atomicReference.compareAndSet(100, 2019) + "\t" + atomicReference.get().toString());
        }, "t2").start();

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

        System.out.println("======ABA问题的解决======");
        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + "\t第一次版本号: " + stamp);
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
            atomicStampedReference.compareAndSet(100,101,
                    atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName() + "\t第二次版本号: " + atomicStampedReference.getStamp());
            atomicStampedReference.compareAndSet(101,100,
                    atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName() + "\t第三次版本号: " + atomicStampedReference.getStamp());
        }, "t3").start();

        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName() + "\t第一次版本号: " + stamp);
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            boolean result=atomicStampedReference.compareAndSet(100,2019,
                    stamp,stamp+1);
            System.out.println(Thread.currentThread().getName()+"\t修改成功与否:"+result+"  当前最新版本号"+atomicStampedReference.getStamp());
            System.out.println(Thread.currentThread().getName()+"\t当前实际值:"+atomicStampedReference.getReference());
        }, "t4").start();
    }
}
ABA问题的产生和解决方案

(3)CAS实现原子操作的三大问题。

     CAS虽然采用自旋的方式高效的解决了原子操作,但任然存在三个问题.

  1. ABA问题。
  2. 循环时间长开销大。
  3. 只能保证一个共享变量的原子操作。

原文链接:https://www.cnblogs.com/2019wxw/p/11650673.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:Java连载38-对象封装性格式、构造方法

下一篇:java当中请给出一个oracle的helloworld例子