美文网首页
面试刷题22:CAS和AQS是什么?

面试刷题22:CAS和AQS是什么?

作者: 李福春carter | 来源:发表于2020-03-31 10:57 被阅读0次
    image.png

    <br />
    <br />
    <br />java并发包提供的同步工具和线程池,底层是基于什么原理来设计和实现的呢?这个非常重要。<br />
    <br />
    <br />我是李福春,我在准备面试,今天的题目是:<br />
    <br />CAS和AQS是什么?<br />
    <br />答:CAS是一系列的操作集合,获取当前值进行计算,如果当前值没有改变,表示线程没有被占用,直接更新成功,否则,进行重试或者返回成功或者失败。 他是java并发工具包中lock-free的基础吗,依赖底层的cpu提供的特定指令实现。底层依赖于Unsafe的本地对象来实现。<br />

    AQS: 全称是AbstractQueuedSynchronizier,抽象队列同步器;他是各种同步工具锁的基础,比如ReentrantLock, CyclicBairier都是基于AQS来实现的。

    CAS

    <br />以AtomicInteger为例子来分析一下CAS的应用。<br />
    <br />首先看内部结构:<br />

    image.png

    <br />
    <br />然后分析一下他的一个利用CAS实现的原子操作。

    public final int getAndAddInt(Object o, long offset, int delta) {
        int v;
        do {
            v = getIntVolatile(o, offset);
        } while (!weakCompareAndSetInt(o, offset, v, v + delta));
        return v;
    }
    

    这是一个自旋操作,利用Unsafe比较内存的偏移量,基于cpu指令保证修改的原子可见性。<br />
    <br />
    <br />使用CAS也是有缺点的:<br />1,自旋次数是假定冲突情况很少的理想情况,但是情况不理想容易过度消耗CPU;<br />2, ABA问题,一般使用加版本号的 AtomicStampedRefence来搞定;<br />
    <br />
    <br />在实际的工作中如何使用CAS来保证同步操作呢?<br />
    <br />可以基于AtomicFieldLongUpdater来实现。比如下面是一个基于CAS实现的同步更新数据库索引的例子,代码如下:<br />

     public static class AtomicBTreePartition{
    
            private volatile long lock;
    
            private static final AtomicLongFieldUpdater<AtomicBTreePartition>
                lockFieldUpdater
                    =AtomicLongFieldUpdater
                .newUpdater(AtomicBTreePartition.class,"lock");
    
            public void acquireLock(){
    
                long t = Thread.currentThread().getId();
    
                while (!lockFieldUpdater.compareAndSet(this, 0, 1)){
                    //数据库操作
                }
            }
    
            public void releaseLock(){
    
            }
    
        }
    

    <br />
    <br />
    <br />

    AQS

    她的组成核心主要有3个部分。<br />

    file

    <br />下面以ReentrantLock的非公平锁为例,分析一下它的加锁和释放锁的实现。<br />加锁操作代码:

      public void lock() {
            sync.acquire(1);
        }
    

    继续跟进:

    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
    

    <br />非公平锁的获取锁操作:

    final boolean nonfairTryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();// 获取当前AQS内部状态量
        if (c == 0) {
            // 0表示无人占有,则直接用CAS修改状态位,
          if (compareAndSetState(0, acquires)) {
              // 不检查排队情况,直接争抢
              setExclusiveOwnerThread(current);  
             //并设置当前线程独占锁
              return true;
          }
        } else if (current == getExclusiveOwnerThread()) { 
            //即使状态不是0,也可能当前线程是锁持有者,因为这是再入锁
          int nextc = c + acquires;
          if (nextc < 0) // overflow
              throw new Error("Maximum lock count exceeded");
          setState(nextc);
          return true;
      }
      return false;
    }
    

    排队竞争:

    final boolean acquireQueued(final Node node, int arg) {
          boolean interrupted = false;
          try {
          for (;;) {// 循环
              final Node p = node.predecessor();// 获取前一个节点
              if (p == head && tryAcquire(arg)) { 
                  // 如果前一个节点是头结点,表示当前节点合适去tryAcquire
                  setHead(node); // acquire成功,则设置新的头节点
                  p.next = null; // 将前面节点对当前节点的引用清空
                  return interrupted;
              }
              if (shouldParkAfterFailedAcquire(p, node)) 
                  // 检查是否失败后需要park
                  interrupted |= parkAndCheckInterrupt();
          }
           } catch (Throwable t) {
          cancelAcquire(node);// 出现异常,取消
          if (interrupted)
                  selfInterrupt();
          throw t;
          }
    
    

    小结

    <br />本节介绍了CAS和AQS的概念,然后以AtomicInteger为例切入原子操作是怎么利用CAS来保证的。<br />最后,以ReentrantLock的加锁操作,跟进了是如何利用AQS来保证内部的不同操作的。<br />
    <br />算是初步探究了同步的实现原理。<br />
    <br />
    <br />


    image.png

    原创不易,转载请注明出处。

    相关文章

      网友评论

          本文标题:面试刷题22:CAS和AQS是什么?

          本文链接:https://www.haomeiwen.com/subject/rkxwuhtx.html