AQS学习笔记

一、使线程进入等待状态和唤醒状态的三种方法

1、使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒线程,需配合synchronized关键字使用

2、使用JUC包中的Condition的await()方法让线程等待,使用signal()方法唤醒线程

3、LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程

 

其中,LockSupport实现了线程的等待唤醒机制,可以认为是wait/notify的改良加强版,其方法park()和unpark()分别实现了线程的阻塞和解除阻塞

 抢到资源的线程,直接使用资源来处理业务逻辑,抢不到资源的线程必然涉及到一种排队等候机制。抢占资源失败的线程继续去等待(类似银行业务办理窗口都满了,暂时没有受理窗口的顾客只能去后可取排队等候),但等候线程仍然保留获取锁的可能且获取锁的流程仍然在继续(候客区的顾客也在等着叫号,轮到了再去受理窗口办理业务)。

既然说到了排队等候机制,那么就一定会有某种形式的队列,这样的队列是什么样的数据结构呢?

如果共享资源被占用,就需要一定的阻塞等待唤醒机制来保证锁的分配。这个机制主要是使用的CLH队列的变体实现的,将暂时获取不到锁的线程加入到队列中,这个队列就是AQS的抽象表现。它将请求共享资源的线程封装成队列的节点(Node),通过CAS、自旋以及LockSupport.park()的方式,维护state变量的状态,使并发达到同步的控制效果。

二、ReentrantLock核心类图

ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphore的核心功能都是依赖AbstractQueueSynchronizer(抽象队列同步器,简称AQS)实现的,以ReentrantLock为例看一下其核心类图如下:

 

 

 

 

 

 

 

 

 

 

三、AQS基本结构

AQS是用来构建锁或者其他同步器组件的重量级基础框架及整个JUC体系的基石,通过内置的FIFO队列来完成资源的获取和线程的排队工作,并通过一个int类型的变量表示持有锁的状态。

CLH队列(FIFO)是一个单向链表,AQS中的队列是CLH变体的虚拟双向队列FIFO

 

 

 

 

 

 

 

四、AQS工作原理

 

posted @ 2025-01-24 16:28  达摩克利斯之剑  阅读(20)  评论(0)    收藏  举报