兜兜零元 发表于 2022-9-16 17:15:11

Java AQS锁实现原理



 整体介绍

概念

https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuLzM4MDVkNzQ3NzcxOTQ3ZGJiYzRlMDhkOWJkNjBjMGJjLnBuZw==https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDIyLmNuYmxvZ3MuY29tL2Jsb2cvMjkxMDI1Mi8yMDIyMDgvMjkxMDI1Mi0yMDIyMDgxNDE0MTM0NzcwNC0xOTIwMDUyMS5naWY=​

 
 
首先阅读一下类的源码注释,可以知道,这几个接口是最关键的。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuLzRiODkwM2EwNWUxZDQ3YzI5M2UwYWE0Y2I0NzdmYjlkLnBuZw==https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDIyLmNuYmxvZ3MuY29tL2Jsb2cvMjkxMDI1Mi8yMDIyMDgvMjkxMDI1Mi0yMDIyMDgxNDE0MTM0NzcwNC0xOTIwMDUyMS5naWY=​

 
这几个方法是使用AQS类的关键,只有这几个方法是可以定制的,其他方法几乎都是final的,不可修改。
从代码实现上看,能看到的变量几乎都是volatile的,能看到的方法几乎都是CAS或者Unsafe类的原子方法。
 
接下来我们来整理一下这个类的字段和方法,这里我们主要关注private字段和public方法。
字段

volatile int state:同步状态。
volatile Node head:等待队列的头,延迟初始化。
volatile Node tail:等待队列的尾部。初始化后,仅通过casTail修改。
 
方法

获取锁:
acquire(int arg)
acquireShared(int arg)
 
释放锁:
release(int arg)
releaseShared(int arg)
 
等待队列:
hasQueuedThreads()
getFirstQueuedThread()
isQueued(Thread thread)
getQueuedThreads()
getExclusiveQueuedThreads()
getSharedQueuedThreads()
 
条件对象ConditionObject:
await()
signal()
 
架构

AQS整体结构,包括加锁/释放锁,条件对象await/signal。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuLzQyYzU1ZjA0NGJmZjQwY2FiNDcwMGE5Y2JhNjkxOWJkLnBuZw==https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDIyLmNuYmxvZ3MuY29tL2Jsb2cvMjkxMDI1Mi8yMDIyMDgvMjkxMDI1Mi0yMDIyMDgxNDE0MTM0NzcwNC0xOTIwMDUyMS5naWY=​

 
功能说明



数据结构
锁的数据结构
 
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuLzk1ZjZlOGM0Mjg0MzQ4OGViYjYzNzRmYjUwNzBkM2UyLnBuZw==https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDIyLmNuYmxvZ3MuY29tL2Jsb2cvMjkxMDI1Mi8yMDIyMDgvMjkxMDI1Mi0yMDIyMDgxNDE0MTM0NzcwNC0xOTIwMDUyMS5naWY=

 
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuLzM1NDdiNjE2NzEzMzRhZTg4N2M4OWNiZjNlMjBkZGU1LnBuZw==https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDIyLmNuYmxvZ3MuY29tL2Jsb2cvMjkxMDI1Mi8yMDIyMDgvMjkxMDI1Mi0yMDIyMDgxNDE0MTM0NzcwNC0xOTIwMDUyMS5naWY=​ 
 
一个状态字段state表示同步状态,0表示没有锁竞争,1表示有锁竞争。
head跟tail分别是等待队列的头节点和尾节点,该等待队列是用双向链表实现的。
 
 
 
 
 
节点的数据结构
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuLzMyYTRjZjFmZmY1NDRkMWU5M2JhZTQ0ZTNmNjE1MWQwLnBuZw==

 
 
prev:前驱节点
next:后继节点
waiter:等待锁的线程
status:节点状态
 
节点https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuLzU2ZGE3NjRmYThkZjQ0Yjg5MTRkMDU2Y2JiMTIwMGNlLnBuZw==https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDIyLmNuYmxvZ3MuY29tL2Jsb2cvMjkxMDI1Mi8yMDIyMDgvMjkxMDI1Mi0yMDIyMDgxNDE0MTM0NzcwNC0xOTIwMDUyMS5naWY= 
 
节点状态其实有4种:
取消状态:status1,独占锁并发数=1。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuL2QzMjcxMzJmODQwNzRmMzNhZTZiMzllMjAwNmUyY2ZlLnBuZw==https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDIyLmNuYmxvZ3MuY29tL2Jsb2cvMjkxMDI1Mi8yMDIyMDgvMjkxMDI1Mi0yMDIyMDgxNDE0MTM0NzcwNC0xOTIwMDUyMS5naWY=​ 
 
共享锁实现过程
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuL2QzMDJiNzJjYTI0YjQzZjRhZThlYTczNzIxMjJkMmJkLnBuZw==https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDIyLmNuYmxvZ3MuY29tL2Jsb2cvMjkxMDI1Mi8yMDIyMDgvMjkxMDI1Mi0yMDIyMDgxNDE0MTM0NzcwNC0xOTIwMDUyMS5naWY=

 
 
 
 
1.tryAcquireShared
这是一个protected方法,在Semaphore里实现了FairSync和NonfairSync,也就是公平锁和非公平锁。
1-1.FairSync in Semaphore
 
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWctYmxvZy5jc2RuaW1nLmNuLzM2MGQwY2VkYmJmYzQ4MGZiYjk0NzcyOWQyZDJkMjlmLnBuZw==https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pbWcyMDIyLmNuYmxvZ3MuY29tL2Jsb2cvMjkxMDI1Mi8yMDIyMDgvMjkxMDI1Mi0yMDIyMDgxNDE0MTM0NzcwNC0xOTIwMDUyMS5naWY=​
 
如果有前驱节点在等待,返回失败;

如果剩余的并发数
页: [1]
查看完整版本: Java AQS锁实现原理