Java资源分享网 - 专业的Java学习网站 学Java,上Java资源分享网
【并发编程】简单化理解AQS和ReentrantLock PDF 下载
发布于:2024-05-09 09:30:50
(假如点击没反应,多刷新两次就OK!)

【并发编程】简单化理解AQS和ReentrantLock  PDF 下载 图1

 

 

资料内容:

1、什么是AQS
Java 中, AQS AbstractQueuedSynchronizer 的简称,直译过来是抽象队列
同步器。 AbstractQueuedSynchronizer 是一个提供了基于 FIFO 等待队列实现的同步器
框架,是 Java 并发库中锁和同步器的核心实现之一。它允许开发人员通过继承
AQS 类来实现自
定义同步器,从而为多线程程序提供可靠的同步机制。
AQS 核心思想是,将等待共享资源的线程封装在一个 FIFO 队列中,然后用 CAS
作等原子操作来修改该队列中的头结点和尾结点。对于独占式同步器(例如
ReentrantLock ), AQS 还提供了一个 state 变量,用于记录当前占用该同步器的线程
数。每次执行 acquire 操作时,线程会尝试获取同步器的状态。如果成功获取,则该线程可以继
续执行;否则,需要一定的阻塞等待唤醒机制来保证锁的分配, AQS 中会将竞争共享资源失败的线
程添加到一个变体的 CLH 队列中。
 
1 public abstract class AbstractQueuedSynchronizer
2  extends AbstractOwnableSynchronizer implements
java.io.Serializable {
3 // CLH 变体队列头、尾节点
4    private transient volatile Node head;
5 private transient volatile Node tail;
6 // AQS 同步状态
7   private volatile int state;
8 // CAS 方式更新 state
9 protected final boolean compareAndSetState(int expect, int
update) {
10        return unsafe.compareAndSwapInt(this, stateOffset, expect,
update);
11   }
12 }

 

简单来说, AQS Java中的一个抽象类,为开发者提供了一种非常灵活的同步机制,可
以适用于多种场景,相比较于传统的 synchronized 关键字更加高效和可定制化。
 
2、谈谈CLH队列
CLH(CraigLandin and Hagersten) 队列,是 单向链表实现的队列。申请线程只在本
地变量上自旋,它不断轮询前驱的状态,如果发现 前驱节点释放了锁就结束自旋,其主要有以下特
点:
1. CLH 队列是一个单向链表,保持 FIFO 先进先出的队列特性;独占锁
共享锁
独占锁
不可共存
不可共存
共享锁
不可共存
可共存
2. 通过 tail 尾节点(原子引用)来构建队列,总是指向最后一个节点
3. 未获得锁节点会进行自旋,而不是切换线程状态;
4. 并发高时性能较差,因为未获得锁节点不断轮训前驱节点的状态来查看是否获得锁。
 
AQS 中的队列是 CLH 变体的虚拟双向队列,通过将每条请求共享资源的线程封装成一个节
点来实现锁的分配,相对于普通的 CLH 队列来说,其主要有以下特点:
1. AQS 中队列是个双向链表,也是 FIFO 先进先出的特性;
2. 通过 Head Tail 头尾两个节点来组成队列结构,通过 volatile 修饰保证可
见性;
3. Head 指向节点为已获得锁的节点,是一个虚拟节点,节点本身不持有具体线程;
4. 获取不到同步状态,会将节点进行自旋获取锁,自旋一定次数失败后会将线程阻塞,相对
CLH 队列性能较好。
 
3、独占锁与共享锁
独占锁也叫排它锁,是指该锁一次只能被一个线程所持有,如果别的线程想要获取锁,只有等到
持有锁线程释放。获得排它锁的线程即能读数据又能修改数据,与之对立的就是共享锁。
共享锁是指该锁可被多个线程所持有。如果线程T对数据A加上共享锁后,则其他线程只能对A
加共享锁,不能加排它锁。获得共享锁的线程只能读数据,不能修改数据。