0、AQS 原理说明
0.1、同步队列(FIFO) - 节点 (ADT)
0.2、同步状态
0.3、锁持有线程
0.4、条件队列(condition)
11、下面结合锁的独占/共享2种特性,以及独占/共享下公平和非公平的具体实现,以及在细化到公平/非公平下的重入和不可重入的具体实现
private transient volatile Node head; // CLH队列的队首
private transient volatile Node tail; // CLH队列的队尾
// CLH队列的节点
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
// 线程已被取消,对应的waitStatus的值
static final int CANCELLED = 1;
// “当前线程的后继线程需要被unpark(唤醒)”,对应的waitStatus的值。
// 一般发生情况是:当前线程的后继线程处于阻塞状态,而当前线程被release或cancel掉,因此需要唤醒当前线程的后继线程。
static final int SIGNAL = -1;
// 线程(处在Condition休眠状态)在等待Condition唤醒,对应的waitStatus的值
static final int CONDITION = -2;
// (共享锁)其它线程获取到“共享锁”,对应的waitStatus的值
static final int PROPAGATE = -3;
// waitStatus为“CANCELLED, SIGNAL, CONDITION, PROPAGATE”时分别表示不同状态,
// 若waitStatus=0,则意味着当前线程不属于上面的任何一种状态。
volatile int waitStatus;
// 前一节点
volatile Node prev;
// 后一节点
volatile Node next;
// 节点所对应的线程
volatile Thread thread;
// nextWaiter是“区别当前CLH队列是 ‘独占锁’队列 还是 ‘共享锁’队列 的标记”
// 若nextWaiter=SHARED,则CLH队列是“独占锁”队列;
// 若nextWaiter=EXCLUSIVE,(即nextWaiter=null),则CLH队列是“共享锁”队列。
Node nextWaiter;
// “共享锁”则返回true,“独占锁”则返回false。
final boolean isShared() {
return nextWaiter == SHARED;
}
// 返回前一节点
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() { // Used to establish initial head or SHARED marker
}
// 构造函数。thread是节点所对应的线程,mode是用来表示thread的锁是“独占锁”还是“共享锁”。
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
// 构造函数。thread是节点所对应的线程,waitStatus是线程的等待状态。
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
1、独占锁(一):
1.1、获取锁:公平与非公平入队列的步骤以及区别?
1.1.1、公平锁:
1.1.1.1、可重入
1.1.1.2、不可重入
1.1.2、非公平锁:默认
1.1.2.1、可重入
1.1.2.2、不可重入
独占锁模式下,实现非公平可重入的ReentrantLock ,被阻塞线程入队列的区别?
前驱节点 是头节点(队列还没有创建):1、首先T2线程与T1争抢锁时算一次
2.1、判断前驱节点prve 是否为 NULL 头节点。
2.2、创建自己节点初始化队列,再次尝试获取一次。
前驱节点不是 头节点:直接创建节点,入队列,设置前驱节点waitstate = -1;