在 Monitor 内部中,主要有四部分组成,分别是 owner、cxq、EntryList 和 waitSet。
1、其中 owner 表示当前所的持有者,记录是哪一个线程获取了当前锁;
2、cxq 是一个栈结构,EntryList 是一个队列结构,这两部分一起完成了当发生锁竞争时,记录线程的阻塞状态;
3、waitSet 是一个集合结构,当线程执行 wait 方法后会将当前线程存入到 waitSet 集合中进入等待状态,只有当执行 notify 或者 notifyAll 时才会唤醒 waitSet 中的相关线程。
从 waitSet中唤醒的线程并不会马上获取锁,而是会和其他线程一样进行锁的竞争操作。
想要了解为什么要是用 _cxq 和 _EntryList 两个结构来记录阻塞线程? 可以先查看以下链接了解一下 Monitor 的加锁和解锁流程。
(11)重量级锁(Monitor)的加锁和解锁流程?解锁是有顺序的吗?_逐步绽放的海棠花的博客-CSDN博客
从加锁解锁流程可以看出,线程会先进入 cxq ,当 owner 释放后才会将 cxq 中的唤醒进入 EntryList 队列,然后再获取锁。
其实这么做的主要目的是为了防止出现 ABA 问题
具体解释请查看视频讲解:【Java必备知识】为锁正名-第9集-重量级锁阻塞队列为何分成cxq和EntryList_哔哩哔哩_bilibili