Java并发编程- CAS原理

Java并发编程- CAS原理

例子:

/**
 * CAS原理
 * @author wufei
 * @create 2019-07-23 19:03
 **/
public class CAS1 {

    private static  volatile  int m =0;

    //原子性的保证
    private static AtomicInteger atomicInteger = new AtomicInteger(0);

    private static void incress1(){
        m ++;
    }
    private static void incress2(){
        atomicInteger.incrementAndGet();
    }
    public static void main(String[] args) throws InterruptedException{

        Thread[] th1 = new Thread[20];

        for (int i = 0; i < 20; i++) {
            th1[i] = new Thread(new Runnable() {
                public void run() {
                    CAS1.incress1();
                }
            });
            th1[i].start();
            th1[i].join();
        }


        Thread[] th2 = new Thread[20];
        for (int i = 0; i < 20; i++) {
            th2[i] =new Thread(new Runnable() {
                public void run() {
                    CAS1.incress2();
                }
            });
            th2[i].start();
            th2[i].join();
        }
        System.out.println("m: "+m);
        System.out.println("atomicInteger: "+atomicInteger.get());

    }
}

运行都是输出20 20 

反编译:

javap -v  CAS1.class

javap -c  CAS1.class

我们查看的只需要incress1()和incress2()

从编译的class文件可以看出:ingress1方法的m++执行了三个指令,

ingress2方法的atomicInteger.incrementAndGet();执行了一个指令,说明了atomicInteger.incrementAndGet()效率高于m++;

我们来看下atomicInteger.incrementAndGet()源码来分析底层原理:

使用的是sun.misc包下的Unsafe类。

调用的方法getAndAddInt()

参数:var1: 要修改的值

var2: 期望值

var4: 更新的值

意思是要修改的值和期望值对比,如果一样则更新值,否则不更新。

原理过程: 原子性AtomicInteger.

incrementAndGet()方法,通过Unsafe类vm去调用unsafe.cpp--汇编。(需要硬件支持)

 

 

例子2:

线程1 把100 修改了110

线程2 把110修改了100

线程3 把100修改了120

出现了ABA的问题

public class CAS2 {

   static AtomicInteger atomicInteger = new AtomicInteger(100);

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                System.out.println(atomicInteger.compareAndSet(100, 110));
            }
        });
        t1.start();

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(atomicInteger.compareAndSet(110, 100));
            }
        });
        t2.start();

        Thread t3 = new Thread(new Runnable() {
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(atomicInteger.compareAndSet(100, 120));
            }
        });
        t3.start();
    }
}

输出结果:都修改成功了,其实应该t1和t2成功,t3是更新失败的。

 

怎样解决ABA的问题呢?

使用AtomicStampedReference类,使用了版本号来控制

public class CAS3 {
//初始化asr,然后设置了版本号为0
   static AtomicStampedReference asr = new AtomicStampedReference(100,0);
    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                System.out.println(asr.compareAndSet(100, 110, asr.getStamp(), asr.getStamp() + 1));
                System.out.println(asr.compareAndSet(110, 100, asr.getStamp(), asr.getStamp() + 1));
            }
        });
        t1.start();

        Thread t2 = new Thread(new Runnable() {
            public void run() {
             int  st =   asr.getStamp();//获取版本号
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(asr.compareAndSet(110, 100, st, st+ 1));

            }
        });
        t2.start();
    }
}

运行结果:

 

CAS的使用场景:

1.应用于简单的数据计算

2.适合线程冲突少的场景

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值