2.1 类图
今天啰嗦一些,我们一步一步看:
2.2 AQS队列
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
protected AbstractOwnableSynchronizer() { }
private transient Thread exclusiveOwnerThread;
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
}
1,Exclusive(独占,只有一个线程能执行,ReentrantLock使用该模式)
2,Share(共享,多个线程可同时执行,Semaphore/CountDownLatch使用该模式)。
/** Marker to indicate a node is waiting in shared mode */
static final Node SHARED = new Node();
/** Marker to indicate a node is waiting in exclusive mode */
static final Node EXCLUSIVE = null;
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 7373984972572414691L;
protected AbstractQueuedSynchronizer() { }
//队列节点
static final class Node {
/** Marker to indicate a node is waiting in shared mode */
static final Node SHARED = new Node();
/** Marker to indicate a node is waiting in exclusive mode */
static final Node EXCLUSIVE = null;
/** waitStatus value to indicate thread has cancelled */ 线程已经被取消,该状态的节点不会再次阻塞。
static final int CANCELLED = 1;
/** waitStatus value to indicate successor's thread needs unparking */ 线程需要去被唤醒
static final int SIGNAL = -1;
/** waitStatus value to indicate thread is waiting on condition */ 线程正在唤醒等待条件
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should //线程的共享锁应该被无条件传播
* unconditionally propagate
*/
static final int PROPAGATE = -3;
//上面四个值就是下面变量waitStatus的值
volatile int waitStatus;
//前一个节点
volatile Node prev;
//下一个节点
volatile Node next;
//当前节点代表的线程
volatile Thread thread;
/**
*等待节点的后继节点。如果当前节点是共享的,那么这个字段是一个SHARED常量,也就是说节点类型(独占和共享)和
*等待队列中的后继节点共用一个字段。(注:比如说当前节点A是共享的,那么它的这个字段是shared,也就是说在这个等
*待队列中,A节点的后继节点也是shared。如果A节点不是共享的,那么它的nextWaiter就不是一个SHARED常量,即是独
*占的。
*/
Node nextWaiter;
}
//头结点
private transient volatile Node head;
//尾节点
private transient volatile Node tail;
//状态值
private volatile int state;
2.3 开始撸代码
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
2.3.1先搞默认的非公平锁,NonfairSync类的lock方法:
static final class NonfairSync extends Sync {
final void lock() {
if (compareAndSetState(0, 1)) //1
setExclusiveOwnerThread(Thread.currentThread()); //2
else
acquire(1); //3
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires); //4
}
}
public final void acquire(int arg) {//5
if (!tryAcquire(arg) && //6
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //7
selfInterrupt(); //8
}
1,CAS原子性的修改AbstractQueuedSynchronizer#state的值,由0改为1,成功则说明当前线程加锁成功.
2,设置AbstractOwnableSynchronizer#exclusiveOwnerThread的值为当前线程,表示当前锁的拥有者是当前线程。
3,如果1中修改失败,则进入acquire(1)。申请1个state,acquire方法中首先尝试获取锁tryAcquire(),如果获取失败,则将当前线程以独占模式Node.EXCLUSIVE加入等待队列尾部(addWaiter方法)。
4,acquireQueued():以独占无中断模式获取锁,这个方法会一直无限循环,直到获取到资源或者被中断才返回。如果等待过程中被中断则返回true。这里有自旋锁的意思,加入队列中的线程,不断的重试检测是否可以执行任务。
tryAcquire
static final class NonfairSync extends Sync {
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();//:1、获取volatile int state的值
if (c == 0) {//2:state=0表示当前可以加锁
if (compareAndSetState(0, acquires)) {//CAS将state设置为acquires的值
setExclusiveOwnerThread(current);//设置当前拥有锁的线程
return true;
}
}
else if (current == getExclusiveOwnerThread()) {//当前锁的拥有者线程是currentThread
int nextc = c + acquires;//将state累加上acquires
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);//设置state的值。由于这里只有获取锁的线程才能执行,所以不会出现并发,不需要额外的加锁处理
//这也是ReentrantLock为什么是可重入锁的原因,同一个线程加多次锁(lock.lock)也就是给state的值累加而已。
return true;
}
return false;//当前锁的拥有者线程不是currentThread,直接返回false,也就是获取锁失败
}
addWaiter和enq
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
//1、首先尝试以快速方式添加到队列末尾
Node pred = tail;//pred指向现有tail末尾节点
if (pred != null) {
//新加入节点的前一个节点是现有AQS队列的tail节点
node.prev = pred;
//CAS原子性的修改tail节点
if (compareAndSetTail(pred, node)) {
//修改成功,新节点成功加入AQS队列,pred节点的next节点指向新的节点
pred.next = node;
return node;
}
}
//2、pred为空,或者修改tail节点失败,
//则走enq方法将节点插入队列
enq(node);
return node;
}
private Node enq(final Node node) {
for(;;) {//CAS
Node t = tail;
if (t == null) {
// 必须初始化。这里是AQS队列为空的情况。
//通过CAS的方式创建head节点,并且tail和head都指向
//同一个节点。
if (compareAndSetHead(new Node()))
//注意这里初始化head节点,并不关联任何线程!!
tail = head;
} else {
//这里变更node节点的prev指针,并且移动tail指针指向node,
//前一个节点的next指向新插入的node
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
nextWaiter = Node.EXCLUSIVE; // Node.EXCLUSIVE值为null
thread = Thread.currentThread();
waitStatus = 0;// 默认是0
acquireQueued
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;//是否获取到资源
try {
boolean interrupted = false;//是否中断
for (;;) {
//获取前一个节点
final Node p = node.predecessor();
//如果当前node节点是第二个节点,紧跟在head后面,
//那么tryAcquire尝试获取资源
if (p == head && tryAcquire(arg)) {
setHead(node);//获取锁成功,当前节点成为head节点
p.next = null; // 目的:辅助GC
failed = false;
return interrupted;//返回是否中断过
}
//当shouldParkAfterFailedAcquire返回成功,
//也就是前驱节点是Node.SIGNAL状态时,
//进行真正的park将当前线程挂起,并且检查中断标记,
//如果是已经中断,则设置interrupted =true。
//如果shouldParkAfterFailedAcquire返回false,
//则重复上述过程,直到获取到资源或者被park。
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);//添加AQS失败,取消任务
}
}
//前面讲过,head节点不与任何线程关联,他的thread是null,
//当然head节点的prev肯定也是null
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
//在Acquire失败后,是否要park中断
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws= pred.waitStatus;//获取到上一个节点的waitStatus
if (ws == Node.SIGNAL)//前面讲到当一个节点状态时SIGNAL时,
//他有责任唤醒后面的节点。所以这里判断前驱节点是SIGNAL状态,
//则可以安心的park中断了。
return true;
if (ws > 0) {
/*
* 过滤掉中间cancel状态的节点
* 前驱节点被取消的情况(线程允许被取消哦)。向前遍历,
* 直到找到一个waitStatus大于0的(不是取消状态或初始状态)
* 的节点,该节点设置为当前node的前驱节点。
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* 修改前驱节点的WaitStatus为Node.SIGNAL。
* 明确前驱节点必须为Node.SIGNAL,当前节点才可以park
* 注意,这个CAS也可能会失败,因为前驱节点的WaitStatus状态
* 可能会发生变化
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
//阻塞当前线程
//park并且检查是否被中断过
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
cancelAcquire
private void cancelAcquire(Node node) {
if (node == null)
return;
node.thread = null;
// 跳过中间CANCELLED状态的节点
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
Node predNext = pred.next;
// 将node设置为CANCELLED状态
node.waitStatus = Node.CANCELLED;
// 如果当前节点是tail节点,则直接移除
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {//如果pred不是head节点并且是SIGNAL 状态,
//或者可以设置为SIGNAL 状态,
//那么将pred的next设置为node.next,也就是移除当前节点
Node next = node.next;
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
unparkSuccessor(node);//唤醒node的后继节点
}
node.next = node; // help GC
}
}
private void unparkSuccessor(Node node) {
//如果waitStatus为负数,则将其设置为0(允许失败)
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
//唤醒当前节点后面的节点。通常是紧随的next节点,
//但是当next被取消或者为空,则从tail到node之间的所有节点,
//往后往前查找直到找到一个waitStatus <=0的节点,将其唤醒unpark
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
1、设置thread变量为空,并且设置状态为canceled
2、跳过中间的已经被取消的节点
3、如果当前节点是tail节点,则直接移除。否则:
4、如果其前驱节点不是head节点并且(前驱节点是SIGNAL状态,或者可以被设置为SIGNAL状态),那么将当前节点移除。否则通过LockSupport.unpark()唤醒node的后继节点
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//这里,先会检查是否有任何线程等待获取的时间长于当前线程。
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
2.4 最后,释放锁
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) {//尝试释放资源 state
Node h = head;
if (h != null && h.waitStatus != 0)//如果AQS不为空,并且头节点的waitStatus不是0,之前在shouldParkAfterFailedAcquire方法内设置成了-1
unparkSuccessor(h);//unpark后继节点
return true;
}
return false;
}
//这里不需要加锁,因为只有获取锁的线程才会来释放锁,
//所以这里直接将state减去releases即可
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
//
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)//注意这里是从AQS队列的尾节点开始查找的,
//找到最后一个 waitStatus<=0 的那个节点,将其唤醒。
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
【完】