Java中关于AbstractQueuedSynchronizer的入门(一)

备注:博文仅仅是学习过程中的零散记录,后期整理。

 AbstractQueuedSynchronizer的简单介绍可以网上搜索,简单了解字段作用。

 

示例代码,分析获取锁的过程:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class AQS {
    public static void main(String[] args) {

        Lock lock = new ReentrantLock();

        lock.lock();

        // do something

        lock.unlock();

    }

}

调用lock方法,然后间接调用:

    /**
     * Sync object for non-fair locks
     */
    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))//更新state的状态值,state是用来记录获取锁的情况。state=0的话则锁没有人获取,当大于0时候表示锁被获取。重入次数。
                setExclusiveOwnerThread(Thread.currentThread()); //AQS的exclusiveOwnerThread成员,记录当前获取锁的线程
            else
                acquire(1);
        }

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

调用如上代码的lock方法,其中的compareAndSetState调用底层操作系统的CAS方法,是一个原子操作。到此就完成了获取锁。

 

 

接下来看看重入锁申请过程,java.util.concurrent.locks.ReentrantLock.Sync.nonfairTryAcquire(int):

        /**
         * 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(); //当获取重入锁时候,判断当前线程和之前申请锁的线程是否是一个?如果不是一个的话则直接返回false
            int c = getState();
            if (c == 0) { //第一次获取锁时,state为0
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
      //如果不是第一次的话,则重入锁
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires; //acquires参数每一次获取锁时候,参数acquires都为1,代表依次获取锁。nextc是当前一共获取锁的次数
                if (nextc < 0) // overflow ,重入次数过多,导致大于Int最大值溢出,抛异常
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);//更新state状态值
                return true; //获取锁成功
            }
            return false;
        }

接下来看看释放锁的过程,java.util.concurrent.locks.ReentrantLock.Sync.tryRelease(int):

      //unlock最终调用这个方法释放锁
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases; //判断state的值,释放锁进行一次减1操作
            if (Thread.currentThread() != getExclusiveOwnerThread())//判断释放锁的线程和当初获取锁的线程是否是一个线程,不是的话则抛异常
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {//如果锁已经彻底释放,则将获取锁的线程设置为null
                free = true;
                setExclusiveOwnerThread(null);
            }
            setState(c);//更新state的状态
            return free;
        }

重入锁的释放同上。

 

posted @ 2017-10-20 13:15  bf378  阅读(308)  评论(0编辑  收藏  举报