ReentrantLock
Lock
impl
static Sync
static final FairSync
static final NoFairSync
extend
AQS
extend
state
CLH
装填元素
装填机制
哨兵Node
(空节点)
线程Node
封装的线程
节点等待的
状态
前驱节点
后继节点
工作机制
构造方法是
否带参数
是
否
是否为true
是
公平锁
非公平锁
否
抢锁
抢锁成功
是
AOS
extend
记录锁的持
有者线程
注册锁的持
有者
否
首先判断等待队列中是否有等待
的节点
入队列有
否
尝试获取锁
成功
注册持有锁
线程的持有
者
失败
尾结点是否
为空
是 初始化队列
否
加入队列尾
部
判断前驱节
点是否为头
节点
否
是
再次尝试获取
锁
1设置前驱节点的等待状态为-1
2 用LoxkSport 阻塞线程
失败
成功
注册锁的持有
者线程
0:锁空闲
1锁被持有
state:
head
tail
ws:0
thread:null
ws:0
thread:B
ws:0
thread:
C
ws:0
thread:
D
1 首先线程A过来,发现锁的状态为0,即锁是空闲的,则A把锁的状态由0改为1,并在持有锁线程登记处把自己的名字登记
上,此刻A便持有锁;
2在A持有锁的同时,线程B过来,发现锁的状态为1,B则需要进入到等待队列中等待;在进入队列时首先要判断队列是否存
在,即获取尾节点,如果尾节点为空,则需要对队列进行初始化,即虚拟一个空节点,队列的头和尾都指向该节点,这个节点
作为占位节点,也称为哨兵节点,主要是明确头部,队列初始化完成之后,封装线程B的节点会从尾部加入到队列,即尾节点
会 指向B,哨兵节点会作为B的前驱节点,B会作为哨兵节点的下一个节点,同时B会把前驱节点,即哨兵节点的等待状态由默认
的0改为1;
3在A仍然持有锁的同时,线程C过来,发现锁的状态为1,则需要进入等待队列中等待,会重复上面B入队的操作,即把尾节点
指向C,然后把C的前驱节点指向B,把B的后继节点指向C,然后吧B的等待状态设置为-1
4:进入到等待队列后,通过LockSupport阻塞线程,至此线程稳稳当当的停留在等待队列中
5出队:当线程A操作完释放锁,就会把持有锁的线程设置为null,同时把锁的状态设置为0,如果这一步成功,就获取头节点,
如果头节点不为空,就找到头节点下一个等待状态为-1的节点进行唤醒;被唤醒的线程开始抢锁,抢锁成功在持有锁,失败则
依然要进入队列等待;
持有锁线程登记处: