CAS

  CAS是一种常用的硬件同步原语,即由一组计算机硬件提供的原子操作。

  CAS的逻辑:

    有三个参数:p-要改变变量的指针;old-旧值;new-新值。执行时先比较p和old值是不是相等,如果相等,就把new赋值给p,并返回true.否则不改变,返回false。

  java在1.5之后引入CAS,主要放在JUC的atomic包下,如下图:

  

  注意在使用CAS时出现ABA问题。

 

     接下来用CAS 来实现转账问题(我们让账户的初始值为 0,然后启动多个协程来并发执行 10000 次转账,每次往账户中转入 1 元,全部转账执行完成后,账户中的余额应该正好是 10000 元)。

  

package cas;

import org.springframework.util.StopWatch;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author liupengr
 * @date 2020/2/20 19:40
 */
public class CASTest implements Runnable{

    private static  AtomicInteger num=new AtomicInteger(0);
    private static CountDownLatch countDownLatch=new CountDownLatch(10000);

    @Override
    public void run() {
        while (!num.compareAndSet(num.get(),num.get()+1)){ }
        countDownLatch.countDown();
    }

    public static void main(String[] args) throws InterruptedException {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(10000, 10000, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        for (int i = 0; i < 10000; i ++) {
            executor.execute(new CASTest());
        }
        countDownLatch.await();
        System.out.println(num.get());
        System.out.println("消耗:" + stopWatch.getTotalTimeMillis() + "ms");
    }
}

运行结果:

  

 

posted @ 2020-02-20 19:57  以梦为码  阅读(412)  评论(0编辑  收藏  举报