CAS小总结

什么是CAS

CAS底层是使用了unsafe类

 要注意,其中用学过的volatile修饰了value,使修改了value以后其他线程可见,其他线程就可以compare and swap

代码展示CAS

	/*
	* CAS:Compare and swap [比较并交换]
	* */
	public class AtomicIntegerDemo {
	    public static void main(String[] args) {
	        AtomicInteger atomicInteger=new AtomicInteger(5);
	        //true 2019
	        System.out.println(atomicInteger.compareAndSet(5, 2019)+"\t"+atomicInteger.get());
	        //false 2019
	        System.out.println(atomicInteger.compareAndSet(5, 2222)+"\t"+atomicInteger.get());
	    }
	}

上图的代码是new了一个AtomicIntrger,这只针对了整数,那是否也可以对对象进行CAS呢,答案是可以的,我们可以使用AtomicReference,详情见如下代码

 

CAS通过AtomicReference实现自旋锁

 CAS的两大缺点

  • ①. 循环时间长开销很大
  • 如果一直失败就会一直尝试
  • ②.容易造成ABA问题
  • ABA问题:改了一次,又改回来,会让计算机以为没有改 注意:AtomicStampedReference用来解决AtomicInteger中的ABA问题,该demo企图将integer的值从0一直增长到1000,但当integer的值增长到128后,将停止增长。出现该现象有两点原因:
  • 使用int类型而非Integer保存当前值
    Interger对-128~127的缓存[这个范围才有效,不在这个范围comareAndSet会一直返回false
    ————————————————
    版权声明:本文为CSDN博主「所得皆惊喜」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/TZ845195485/article/details/117712307

  • /**
     * Description: ABA问题的解决
     *
     * @author veliger@163.com
     * @date 2019-04-12 21:30
     **/
    public class ABADemo {
        private static AtomicReference<Integer> atomicReference=new AtomicReference<>(100);
        private static AtomicStampedReference<Integer> stampedReference=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(()->{
                //先暂停1秒 保证完成ABA
                try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
                System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get());
            },"t2").start();
            try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println("===以下是ABA问题的解决===");
    
            new Thread(()->{
                int stamp = stampedReference.getStamp();
                System.out.println(Thread.currentThread().getName()+"\t 第1次版本号"+stamp+"\t值是"+stampedReference.getReference());
                //暂停1秒钟t3线程
                try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
    
                stampedReference.compareAndSet(100,101,stampedReference.getStamp(),stampedReference.getStamp()+1);
                System.out.println(Thread.currentThread().getName()+"\t 第2次版本号"+stampedReference.getStamp()+"\t值是"+stampedReference.getReference());
                stampedReference.compareAndSet(101,100,stampedReference.getStamp(),stampedReference.getStamp()+1);
                System.out.println(Thread.currentThread().getName()+"\t 第3次版本号"+stampedReference.getStamp()+"\t值是"+stampedReference.getReference());
            },"t3").start();
    
            new Thread(()->{
                int stamp = stampedReference.getStamp();
                System.out.println(Thread.currentThread().getName()+"\t 第1次版本号"+stamp+"\t值是"+stampedReference.getReference());
                //保证线程3完成1次ABA
                try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
                boolean result = stampedReference.compareAndSet(100, 2019, stamp, stamp + 1);
                System.out.println(Thread.currentThread().getName()+"\t 修改成功否"+result+"\t最新版本号"+stampedReference.getStamp());
                System.out.println("最新的值\t"+stampedReference.getReference());
            },"t4").start();
        }
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值