Java多线程源码分析之:AQS常用应用
Java多线程源码分析之:AQS常用应用
之前我们说到了aqs的基本方法,主要是acquire()获取锁和release()释放锁,这是aqs中阻塞队列的方法,还有两个条件队列的基本方法:await()等待和signal。当aqs里面还有不少扩展方法,它们其实是为了支持不同的并发工具来定义的。
常见的主要有:
- Semaphore:可以理解为操作系统中的信号量,可以看作一种共享锁。
- CountDownLatch:可以看作一种计数器,在没到达指定数字时会阻塞所有线程,否则就会同时唤醒所有线程。(计数器是递减,到达0会释放所有线程)
- ReentrantLock:经典的互斥锁,它同样是AQS中条件队列的实现类。
- CyclicBarrier:它是基于ReentrantLock实现的,和CountDownLatch有些类似,也可以看作一种计数器,唯一的区别是当计数器到达0时会重置到开始的数字。
- ReentrantReadWriteLock:读写锁,提供读锁共享写锁阻塞。
- ThreadPoolExecutor:大名鼎鼎的线程池(线程池会单独成篇)
锁的白月光:ReentrantLock
ReentrantLock我没记错的话是我接触的第二个Java锁,第一个是使用最简单的synchronized。
按照惯例,先来看看ReentrantLock类的总体结构:

我买了可以看到,在ReentrantLock中,有三个内部类,包含了lock和unlock等方法。
其中,FairSync为抽象类,负责对AQS进行了进一步的封装,并实现了一些通用方法。
首先来看看FairSync类(我略去了一些不重要的代码)
    abstract static class Sync extends AbstractQueuedSynchronizer {
        //解锁,由子类实现
        abstract void lock();
        /**
         * 非公平锁的实现
         * 这个方法其实就是AQS中的tryAcquire()方法的实现类
         * Sync的子类会通过此方法来实现AQS中的tryAcquire()方法
         * (AQS中的tryAcquire()方法没有具体实现,默认抛出异常)
         */
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            /**
             * 如果看过我之前的AQS文章看到这里应该会一眼懂,这里就是在
             * 用cas修改state的值,也就是获取锁
             * 这里是第一次加锁的情况
             */
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            /**
             * 这里其实是可重入锁的实现,只有持锁线程才能多次加锁
             */
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                {
                    throw new Error("Maximum lock count exceeded");
                }
                setState(nextc);
                return true;
            }
            return false;
        }
        /**
         * AQS中释放锁的实现类
         * 代码其实不难,就是在更改state的值
         */
        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;
        }
    }

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号