浅谈 CAS 及其缺点和解决方案

什么是 CAS 机制?

CAS 英文就是 compare and swap ,也就是比较并交换,首先它是一个原子操作,可以避免被其他线程打断。在Java并发中,我们最初接触的应该就是synchronized关键字了,但是synchronized属于重量级锁,很多时候会引起性能问题,虽然在新的JDK中对其已经进行了优化。volatile也是个不错的选择,但是volatile不能保证原子性,只能在某些场合下使用。那么问题来了,这个 CAS 机制是怎么在不加锁的情况下来保证共享资源的互斥呢?

synchronized补充:首先,synchronized会对第一个线程会有偏向,所以会给第一个线程添加偏向锁,如果偏向锁有其他线程来竞争时,这个锁会升级,变成轻量级锁(多数情况下是自旋锁),再如果这个锁在一定次内还是拿不到共享资源,这个轻量级的锁会进一步升级,成为重量级锁。

共享资源:通俗来讲就是指那些可以被多个不同线程一起使用的数据。

首先我们先来看一个例子

  • 当我们有很多个线程同时访问一个贡献资源时,我们无法保证我们的贡献资源只被一个线程使用,如果要保证只有一个线程使用时,我们最先想到的一般就是加锁。当然我们先看不加锁的情况:
java复制代码    static volatile int NUMBER = 0; //volatile可以保证我们每次取值都是取内存的值(最新值),而不是取栈里面的缓存值

    private static void add() throws InterruptedException {
        Thread.sleep(5); //模拟线程处理数据
        NUMBER++;
    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(100);//栅栏,底层为AQS实现,当里面值变为0时,栅栏才打开继续运行下面代码
        Long start = System.currentTimeMillis();
        for (int i = 0; i < 100; i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j<100; j++){
                        try {
                            add();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    countDownLatch.countDown();
                }
            }).start();
        }
        countDownLatch.await();//等待所有线程运行完
        System.out.println("最后执行结果:" + NUMBER + "。执行时间为:" + (System.currentTimeMillis() - start) + "ms");
    }
//最后执行结果:9637。执行时间为:600ms

当我们在add方法上加上一个锁时,我们可以看到由于加完了锁我们的线程速度慢了很多,当然我们有模拟了线程运行数据的情况。那我们要怎么去优化我们的代码呢?

  • 首先我们要剖析add方法里面的代码,一方面我们在方法上加了锁,导致线程只能串行化,而且线程在方法中sleep了5毫秒,才进行NUMBER++,另一方面**我们在进行NUMBER++中,NUMBER++也并非原子操作。**我们看到代码的注释:
java复制代码    private synchronized static void
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值