• Java多线程源码分析之:AQS常用应用


    Java多线程源码分析之:AQS常用应用

    之前我们说到了aqs的基本方法,主要是acquire()获取锁release()释放锁,这是aqs中阻塞队列的方法,还有两个条件队列的基本方法:await()等待signal。当aqs里面还有不少扩展方法,它们其实是为了支持不同的并发工具来定义的。

    常见的主要有:

    1. Semaphore:可以理解为操作系统中的信号量,可以看作一种共享锁。
    2. CountDownLatch:可以看作一种计数器,在没到达指定数字时会阻塞所有线程,否则就会同时唤醒所有线程。(计数器是递减,到达0会释放所有线程)
    3. ReentrantLock:经典的互斥锁,它同样是AQS中条件队列的实现类。
    4. CyclicBarrier:它是基于ReentrantLock实现的,和CountDownLatch有些类似,也可以看作一种计数器,唯一的区别是当计数器到达0时会重置到开始的数字。
    5. ReentrantReadWriteLock:读写锁,提供读锁共享写锁阻塞。
    6. ThreadPoolExecutor:大名鼎鼎的线程池(线程池会单独成篇)

    锁的白月光:ReentrantLock

    ReentrantLock我没记错的话是我接触的第二个Java锁,第一个是使用最简单的synchronized

    按照惯例,先来看看ReentrantLock类的总体结构:

    image-20220117225537768

    我买了可以看到,在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;
            }
        }
    
  • 相关阅读:
    7.15的一些小练习
    关于turtle画蟒蛇小实例
    Javascript我学之四作用域
    Javascript我学之三函数的参数
    Javascript我学之二函数定义
    JavaScript我学之一变量类型
    叩响C#之门-继承
    《C#高级编程》之泛型--1创建泛型类
    VB6 仿.netWinfrom控件 Anchor属性类
    新写了XmlFile类
  • 原文地址:https://www.cnblogs.com/lovelylm/p/15819105.html
Copyright © 2020-2023  润新知