AQS锁详解

关键 描述
核心思想

总的来说: AQS就是基于底层的同步等待队列,获取volatile修饰的共享变量state,线程通过CAS自旋的改变状态符,若改变成功则获取锁成功,失败则进入同步等待队列进行排队与释放;


① AQS全称为AbstractQueuedSynchronizer(抽象队列同步器),它是基于模板方法的锁同步框架;


② AQS的底层维护了一个用volatile修饰的int类型的state状态字段,用于表示当前共享资源的状态;获取共享资源时是基于CAS的方式进行的;


③ 它支持独占式共享式两种获取资源的方式,并基于此开放了4个模板方法与1个获取资源状态的方法,用于资源的获取与释放;AQS可以通过重写模板方法中对共享资源的获取与释放逻辑,来实现公平锁可重入锁


④ 对于获取不到共享资源的线程,AQS提供了一个双向链表结构的同步队列进行管理;对于调用了await()方法而阻塞的线程,AQS提供了一个单向链表结构的条件队列进行管理;

资源共享方式

AQS定义了两种资源共享方式:独占式、共享式;


1、独占式: 同一时刻只能有一个线程能够获取共享资源,比如ReentrantLock锁。独占式锁又可以分为公平锁 / 非公平锁。对应模板方法为:tryAcquire() 和 tryRelease();


① 公平锁: 线程进入同步队列排序,按先后顺序获取锁;


② 非公平锁: 线程无视同步队列顺序,直接自旋抢锁。达到最大自旋次数后,进入同步等待队列按顺序获取锁。


2、共享式: 同一时刻可以有多个线程获取共享资源,比如信号量 (Semaphore) 和 循环栅栏 (CountDownLatch) 等;对应模板方法为: tryAcquireShared() 和 tryReleaseShared();

同步队列

1、进入同步队列时机: 当共享资源被某个线程占有后,其它请求该资源的线程会被阻塞,进入同步队列排队等待。AQS的底层维护了一个双向链表结构的同步队列,它是一个虚拟队列。不存在队列实例,只存在节点之间的关联关系。


2、Node节点: AQS将每个请求共享资源的线程信息封装成一个Node节点来实现锁的分配与释放。Node节点有四种状态: 只有状态码小于0的节点才需要被唤醒。


① Canceled = 1 (取消): 表示当前节点从同步队列中取消;自旋获取锁出现异常时改为此状态;


② Signal = -1: 表示后继节点的线程处于等待状态,如果当前节点释放同步状态则会通知后继节点,使得后继节点能够运行;


③ Condition = -2: 表示当前节点的线程调用了await()方法,正在条件队列中等待被signal()唤醒,重新变成Signal状态;


④ Propagate = -3: 表示下一次共享式同步状态的获取将会无条件传播下去;

你可能感兴趣的:(多线程与高并发,多线程与高并发,AQS锁)