昨天不是放假嘛,端午然后广州这边疫情+下雨,二少就找了些AQS的资料看看,没错,就是肝!在广州的小伙伴要保护好自己哈,反正听党的话,不要乱跑就是了,哈哈~

AQS中公平锁和非公平锁怎么实现的?

AQS的非公平性如何实现 java aqs 公平锁 非公平锁的实现_可重入


如上图所示,公平锁和非公平锁的代码主要有两处地方有区别:

  • 公平锁调用lock()方法获取锁时,直接抢占锁【acquire(1),见注释1】, 非公平锁调用lock()方法获取锁时,先执行cas获取锁,获取失败后再抢占锁【acquire(1),见注释2】;
  • 调用acquire(1)抢占锁时,若锁没有被占用(state=0)
  • 非公平锁则直接执行cas代码尝试获取锁(见注释3);
  • 公平锁则先检查AQS队列,若AQS队列为空或AQS头节点的后继节点是当前节点(见注释4的hasQueuedPredecessors()方法),则再执行cas代码尝试获取锁(见注释5);

公平锁:

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

    final void lock() {
        acquire(1);//注释1,调用lock()后直接抢占锁
    }
    
    //非公平锁和公平锁都会执行该方法
        public final void acquire(int arg) {
        if (!tryAcquire(arg) &&   
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
        }

    /**
     * Fair version of tryAcquire.  Don't grant access unless
     * recursive call or no waiters or is first.
     */
    protected final boolean tryAcquire(int acquires) {
        final Thread current = Thread.currentThread();
        int c = getState();
        if (c == 0) {
            if (!hasQueuedPredecessors() &&  //hasQueuedPredecessors返回false后可继续执行compareAndSetState=cas
                compareAndSetState(0, acquires)) {  //注释5,cas方法
                setExclusiveOwnerThread(current);//设置占用锁的线程为当前线程,并返回true
                return true;//返回true后拿锁成功,即lock()拿锁成功
            }
        }
        else if (current == getExclusiveOwnerThread()) {
        //已获得锁的线程就是当前线程【getExclusiveOwnerThread()获取占用锁的线程】,则重入拿锁(ReentrantLock是可重入锁)
            int nextc = c + acquires; 
            if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
            setState(nextc);//重新设置同步转态state
            return true;
        }
        return false;
    }
    
    //注释4:若AQS队列为空或AQS头节点的后继节点是当前节点,返回false
    public final boolean hasQueuedPredecessors() {
        // The correctness of this depends on head being initialized
        // before tail and on head.next being accurate if the current
        // thread is first in queue.
        Node t = tail; //AQS队列的尾结点, Read fields in reverse initialization order
        Node h = head;  //AQS队列的头结点
        Node s;
        return h != t && 
            ((s = h.next) == null || s.thread != 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))  //注释2,调用lock()后先执行cas试图获取锁
                setExclusiveOwnerThread(Thread.currentThread());
            else  
                acquire(1); //获取失败后再抢占锁
        }
        
        //非公平锁和公平锁都会执行该方法
        public final void acquire(int arg) {
        if (!tryAcquire(arg) &&   
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
        }

        //锁没有被占用或锁可重入则返回true
        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);  
        }
        
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {  //锁没有被占用
                if (compareAndSetState(0, acquires)) {  //注释3,执行cas
                    setExclusiveOwnerThread(current);  //设置占用锁的线程为当前线程,并返回true
                    return true;//返回true后拿锁成功,即lock()拿锁成功
                }
            }
            else if (current == getExclusiveOwnerThread()) {  
        //已获得锁的线程就是当前线程【getExclusiveOwnerThread()获取当前占用锁的线程】,则重入(ReentrantLock是可重入锁)   
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);//重新设置同步转态state
                return true;
            }
            return false;
        }
    }
}
  • ReentrantLock、Lock、FairSync、NonfairSync、Sync、AbstractQueuedSynchronizer之间的关系
    ReentrantLock实现Lock,并拥有内部类FairSync、NonfairSync、Sync;FairSync、NonfairSync继承Sync,同时Sync继承AbstractQueuedSynchronizer

AQS的非公平性如何实现 java aqs 公平锁 非公平锁的实现_重入锁_02

OK,如果文章哪里有错误或不足,欢迎各位留言。
创作不易,各位的「三连」是二少创作的最大动力!我们下期见!