AQS源码

1.AQS

AQS是AbstractQueueSynchronization,抽象的队列同步器,它是实现同步器的基础组件,如常用的ReentrantLock、Semaphore、CountDownLatch等。

如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中,这个队列就是AQS的抽象表现。它将请求共享资源的线程封装成队列的结点(Node),通过CAS自旋以及LockSupportpark()的方式,维护state变量的状态,使并发达到同步的控制效果。

状态

  • getState():返回同步状态
  • setState(int newState):设置同步状态
  • compareAndSetState(int expect, int update):使用CAS设置同步状态
  • isHeldExclusively():当前线程是否持有资源

独占资源(不响应线程中断)

  • tryAcquire(int arg):独占式获取资源,子类实现
  • acquire(int arg):独占式获取资源模板
  • tryRelease(int arg):独占式释放资源,子类实现
  • release(int arg):独占式释放资源模板

共享资源(不响应线程中断,读写锁的读锁)

  • tryAcquireShared(int arg):共享式获取资源,返回值大于等于0则表示获取成功,否则获取失败,子类实现
  • acquireShared(int arg):共享式获取资源模板
  • tryReleaseShared(int arg):共享式释放资源,子类实现
  • releaseShared(int arg):共享式释放资源模板

AQS的大概结构(如图,借用尚硅谷阳哥的图)

AQS的int变量

在AQS中维护了一个用关键字volatile修饰同步状态变量state ,代表着该共享资源的状态一更改就能被所有线程可见,而AQS的加锁方式本质上就是多个线程通过CAS完成对state值的修改,即volatile保证了可见性和有序性,用cas保证了原子性,当state为0时代表线程可以竞争锁,不为0时代表当前对象锁已经被占有。所以state的具体语义由实现者去定义,现有的ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch定义的state语义都不一样.

  • ReentrantLockstate用来表示是否有锁资源
  • ReentrantReadWriteLockstate16位代表读锁状态,低16位代表写锁状态
  • Semaphorestate用来表示可用信号的个数
  • CountDownLatchstate用来表示计数器的值

2.从ReentrantLock()

大概就是这个流程 一点点的跟。。。。。本人只是了解,不能清晰的解释仅供参考

  public static void main(String[] args) {
        //首先从你new了一个ReentrantLock锁开始 
        ReentrantLock reentrantLock = new ReentrantLock(true); //true表示是公平锁
        reentrantLock.lock();
       
  }

  public ReentrantLock(boolean fair) {
        //true则创建公平锁
        sync = fair ? new FairSync() : new NonfairSync();
   }
 public ReentrantLock() {
        //无参构造时创建的时非公平锁
        sync = new NonfairSync();
  }


 // aqs是lock下面锁实现的底层基处,及ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch都会有个Sync类继承了AbstractQueuedSynchronizer类(也就是AQS)
abstract static class Sync extends AbstractQueuedSynchronizer{
     abstract void lock();

        /**
         * Performs non-fair tryLock.  tryAcquire is implemented in
         * subclasses, but both need nonfair try for trylock method.
         */
        final boolean nonfairTryAcquire(int acquires) {
            //获取当前的线程
            final Thread current = Thread.currentThread();
            //获取资源的状态如果是0可以抢占
            int c = getState();
            if (c == 0) {
                //compareAndSetState(0, acquires)利用cas去尝试修改
                if (compareAndSetState(0, acquires)) {
                    //抢到了进行把setExclusiveOwnerThread中的Thread指向当前线程
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                //当前线程是抢占的线程 可重入++
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                //锁彻底释放资源了
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);
            return free;
        }

        protected final boolean isHeldExclusively() {
       //带有ExclusiveOwnerThread的方法都和AbstractOwnableSynchronizer有关
       //AbstractOwnableSynchronizer有一个 private transient Thread exclusiveOwnerThread;
       //exclusiveOwnerThread就是抢到资源那个把state变成1的线程 也就是抢到锁的线程
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        //下面还有一些方法省略了

}


  static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                //抢到资源了
                  setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }
  //AbstractQueuedSynchronizer类里面的
    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
                acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            //中断标识
            boolean interrupted = false;
            //自旋
            for (; ; ) {
                //获取当前节点的前一个节点
                final Node p = node.predecessor();
                //如果这个节点是哨兵节点 则去抢占一下
                // 先是调用NonfairSync的tryAcquire(实现了父类AQS的)
                //然后最终调用Sync中的nonfairTryAcquire
                if (p == head && tryAcquire(arg)) {
                    //抢占到了 把当前节点设置成头节点 把头节点(哨兵节点清除),
                    //把当前节点变成哨兵节点 最后原来的哨兵节点被gc回收
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                //parkAndCheckInterrupt 方法利用LockSupport来把当前线程等待
                //只有在持有锁释放的线程释放时进行unpark发令牌才能启动
                if (shouldParkAfterFailedAcquire(p, node) &&
                        parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                //取消抢占
                cancelAcquire(node);
        }
    }


    private Node addWaiter(Node mode) {
        //创建节点 因为clh队列是一个个节点组成
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        //因为一开始队列没有节点所以tail为null
        Node pred = tail;
        if (pred != null) {
            //不会null把当前节点的前指针指向上一个尾节点
            node.prev = pred;
            //设置   
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

     private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            //一开始会创建个哨兵节点并将头尾指针指向这个节点
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值