AQS、ReentrantLock源码解读

19 篇文章 0 订阅

先看看这个:https://blog.csdn.net/ym15229994318ym/article/details/107918804
有个大概全貌了解在看这个。

这个老师讲的好:https://www.bilibili.com/video/BV18i4y1C7xt/?p=8&spm_id_from=pageDriver&vd_source=28a57ce91f90cbdd8af472d6cb29d978

1、aqs

aqs本质就是java1中的AbstractQueuedSynchronizer,这个类是aqs并发包的一个基类,CountDownLatch、ReentrantLock、信号量…都是通过他实现的

在AbstractQueuedSynchronizer类中,有几个属性和一个(CLH)双向队列

public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {

    private static final long serialVersionUID = 7373984972572414691L;

    protected AbstractQueuedSynchronizer() {
    }

    static final class Node {
        //共享锁标识
        static final Node SHARED = new Node();
        //排他锁标识
        static final Node EXCLUSIVE = null;

        //如果带有这个标识,证明失效了
        static final int CANCELLED = 1;
        //具有这个标识,说明后继节点需要被唤醒
        static final int SIGNAL = -1;

        static final int CONDITION = -2;

        static final int PROPAGATE = -3;

        // Node对象存储标识的地方
        volatile int waitStatus;

        volatile Node prev;

        volatile Node next;

        //当前Node绑定的线程
        volatile Thread thread;


        Node nextWaiter;


        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        // 返回前驱节点
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {    // Used to establish initial head or SHARED marker 
        }

        Node(Thread thread, Node mode) {     // Used by addWaiter
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) { // Used by Condition
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

    //头结点
    private transient volatile Node head;
		//尾结点
    private transient volatile Node tail;
		
    //当前所状态,(state的值就是获取锁的次数(可重入锁))
    private volatile int state;
    protected final int getState() {
        return state;
    }
    protected final void setState(int newState) {
        state = newState;
    }
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

    static final long spinForTimeoutThreshold = 1000L;

    //说明现在没人排队我是第一个或者替换尾结点时cas设置失败,都会调用这个方法往队列(尾)中塞
    private Node enq(final Node node) {
        //自旋
        for (; ; ) {
            //重新获取当前tail为t
            Node t = tail;
            // t = null时,说明队列中没有排队(没头没尾)我是第一个
            if (t == null) { 
                //cas的创建head结点,并将尾指向该head(初始化等待队列)
                // 注意:这个new Node()是没有意义的(无参构造),只是为了初始化,此时还没有return,继续自旋直到把node插入队尾
                if (compareAndSetHead(new Node()))
                    tail = head;
            // t != null时,说明队列中有排队,往队列(尾)中塞
            // 和addWaiter(Node mode)模式一样,只不过放在自旋中了
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

    //说明获取锁失败,放到等待队列(尾)中等待
    private Node addWaiter(Node mode) {
        // 创建node节点,节点绑定的线程是当前线程,mode是传过来的锁标识(排他锁、、、)
        Node node = new Node(Thread.currentThread(), mode);
        //获取aqs等待队列的尾结点
        Node pred = tail;
        // pred != null时,即说明队列中有排队
        if (pred != null) {
            // 把刚刚创建的前驱指向尾结点
            node.prev = pred;
            //cas的方式把tail设置为当前创建的节点
            if (compareAndSetTail(pred, node)) {
                //将之前的尾结点的next指向当前创建的
                pred.next = node;
                return node;
            }
        }
        // pred = null时,即说明队列中没有排队
        enq(node);
        return node;
    }
  
		//设置头节点,前驱和绑定线程为null(head节点是没有意义的,相当于无参构造)  
    private void setHead(Node node) {
        head = node;
        node.thread = null;
        node.prev = null;
    }
  
    //已经将node加入到了aqs双向等待队列中了
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                //当前的节点的前驱节点
                final Node p = node.predecessor();
                //如果p是头,说明只有我一个,那就再次尝试获取锁资源
                if (p == head && tryAcquire(arg)) {
                    // 尝试获取锁成功了,那就设置当前节点为header(head节点没有意义 头结点获取锁也成功了,所以没啥意义了)
                    // 将thread和prev设置为null,获取锁成功,排队和我没有关系
                    setHead(node);
                    p.next = null; // 置null帮助GC
                    failed = false; // 说明成功,注意finally
                    return interrupted;
                }
                //p不是head,或者head没拿到锁资源
                //shouldParkAfterFailedAcquire():保证上一个节点为有效节点(-1)
                //parkAndCheckInterrupt():shouldParkAfterFailedAcquire()返回为true才会执行,将线程阻塞,等待唤醒获取锁资源
                //为了保证挂起后的都能被唤醒,所以前一个节点必须是有效的(前面节点有效,后继节点才能被唤醒)
                if (shouldParkAfterFailedAcquire(p, node) &&
                    //基于Unsafe的park()挂起线程
                    parkAndCheckInterrupt())
                    //针对fail属性,这里唯一可能出现异常的地方就是jvm内部出现异常,(finally基本不会执行,中断异常)
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
     }
  
     //p不是head,或者head没拿到锁资源
     //pred是前驱节点,node是当前节点
     private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        // 前一个节点的状态
        int ws = pred.waitStatus;
        // 如果上一个节点状态为-1 SIGNAL,一切正常
        if (ws == Node.SIGNAL)
            return true;
        // 如果上一个节点状态  > 0,为1,说明已经生效
        if (ws > 0) {
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            //do...while结束,找到了<=0的节点,即-1的
            // 将重新标识好的最近的有效节点的next指向当前节点
            pred.next = node;
        } else {
            //小于等于0,不等于-1,cas将上一个有效节点状态修改为-1
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
     }
  
     //挂起线程,阻塞等待唤醒
     private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
     }
  
     //取消获取
     private void cancelAcquire(Node node) {
        if (node == null)
            return;
        // 将当前node的线程置为null,竞争锁资源和我没关系了
        node.thread = null;

        //获取当前节点的前驱节点
        Node pred = node.prev;
        while (pred.waitStatus > 0)
            //循环结束,找到前驱中最近的非失效节点
            node.prev = pred = pred.prev;
        //将第一个不是失效节点的后续节点声明出来
        Node predNext = pred.next;

        // 将当前节点置为失效节点(给别的node看的,别的node执行时就类似的跳过继续往前找了)
        node.waitStatus = Node.CANCELLED;

        // 如果当前节点是尾结点,将尾结点设置为最近的有效节点(如果当前节点为尾结点的操作)
        if (node == tail && compareAndSetTail(node, pred)) {
            //用cas方式将尾节点的next设置为null
            compareAndSetNext(pred, predNext, null);
        } else {
            int ws;
            //如果中间节点操作
            //如果上一个节点不是头结点
            if (pred != head &&
                //获取上一个节点状态是否有效
                ((ws = pred.waitStatus) == Node.SIGNAL ||  // pred需要唤醒后继节点的
                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
                pred.thread != null) {
                Node next = node.next;
                if (next != null && next.waitStatus <= 0)
                    compareAndSetNext(pred, predNext, next);//尝试将pred的前驱节点的next指向当前节点得next(必须是有效的next节点)
            } else {
                //头结点,唤醒后继节点
                unparkSuccessor(node);
            }

            node.next = node; // help GC
        }
    }
  
    //......
  
    // 获取锁
    public final void acquire(int arg) {
        //tryAcquire():(子类实现)尝试获取锁,返回true:1、拿到锁资源2、重入成功
        //acquireQueued():(tryAcquire()获取锁失败返回false,短路&&)执行增加到aqs等待队列中
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            //线程中断
            selfInterrupt();
    }
  
    // 设置为当前线程,这个属性exclusiveOwnerThread是aqs的父类aos(AbstractOwnableSynchronizer)提供的
    protected final void setExclusiveOwnerThread(Thread thread) {
        exclusiveOwnerThread = thread;
    }

}

2、ReentrantLock

public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    
    private final Sync sync;

    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        abstract void lock();

        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //直接尝试更新锁状态,没有考虑等待队列中的线程(nonfair)
                if (compareAndSetState(0, acquires)) {
                    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() {
            // While we must in general read state before owner,
            // we don't need to do so to check if current thread is owner
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        // Methods relayed from outer class

        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        final boolean isLocked() {
            return getState() != 0;
        }

        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

    //不公平锁
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        //上锁直接cas比较锁状态
        final void lock() {
            if (compareAndSetState(0, 1))
                //成功设置拥有锁线程为当前线程
                setExclusiveOwnerThread(Thread.currentThread());
            else
                //获取锁
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    //公平锁
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            //获取当前线程锁状态
            int c = getState();
            // c==0表示当前无线程占用锁
            if (c == 0) {
              /**
               * hasQueuedPredecessors():(公平锁)去等待队列查询是否有等待线程 返回false说明没有,就cas设置锁状态
               * compareAndSetState():cas设置当前状态
               */
              if (!hasQueuedPredecessors() &&
                  compareAndSetState(0, acquires)) {
                //等待队列无等待线程,且状态设置成功,就设置当拥有锁的线程为当前线程,返回ture获取锁成功
                setExclusiveOwnerThread(current);
                return true;
              }
            }
            // c!=0表示当有线程占用锁,去判断当前占用锁的线程是不是当前线程
            else if (current == getExclusiveOwnerThread()) {
              // 可重入锁,计数器增加
              int nextc = c + acquires;
              if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
              //设置锁状态
              setState(nextc);
              //返回ture获取锁成功
              return true;
            }
            //当前有线程拥有锁,获取失败
            return false;
        }
    }
    
    //默认非公平锁
    public ReentrantLock() {
        sync = new NonfairSync();
    }
  
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

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

    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

    public void unlock() {
        sync.release(1);
    }
  
    public Condition newCondition() {
        return sync.newCondition();
    }
  
    public int getHoldCount() {
        return sync.getHoldCount();
    }

    public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }

    public boolean isLocked() {
        return sync.isLocked();
    }

    public final boolean isFair() {
        return sync instanceof FairSync;
    }

    protected Thread getOwner() {
        return sync.getOwner();
    }

    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    public final boolean hasQueuedThread(Thread thread) {
        return sync.isQueued(thread);
    }

    public final int getQueueLength() {
        return sync.getQueueLength();
    }

    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }

    public boolean hasWaiters(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

    public int getWaitQueueLength(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

    protected Collection<Thread> getWaitingThreads(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

    public String toString() {
        Thread o = sync.getOwner();
        return super.toString() + ((o == null) ?
                                   "[Unlocked]" :
                                   "[Locked by thread " + o.getName() + "]");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值