1.1
//ReentrantLock.java
//true为公平锁、false为非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
//调用Sync的lock
public void lock() {
sync.lock();
}
//FairSync、NonfairSync继承自Sync。如果是公平锁,将调用FairSync的lock方法
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
}
Sync继承自AbstractQueuedSynchronizer,acquire也是AbstractQueuedSynchronizer的方法
//AbstractQueuedSynchronizer.java
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
1、tryAcquire
//AbstractQueuedSynchronizer.java
/**
* Attempts to acquire in exclusive mode. This method should query
* if the state of the object permits it to be acquired in the
* exclusive mode, and if so to acquire it.
* 独占模式下尝试获取锁,这个方法应该查询独占模式下这个对象是否能被获取
* <p>This method is always invoked by the thread performing
* acquire. If this method reports failure, the acquire method
* may queue the thread, if it is not already queued, until it is
* signalled by a release from some other thread. This can be used
* to implement method {@link Lock#tryLock()}.
* 这个方法经常通过线程去调用acquire方法。如果这个方法返回失败,将这个线程将加入队列,直到其他线程发起释放信号
* <p>The default
* implementation throws {@link UnsupportedOperationException}.
*
* @param arg the acquire argument. This value is always the one
* passed to an acquire method, or is the value saved on entry
* to a condition wait. The value is otherwise uninterpreted
* and can represent anything you like.
* 这个值将被传到acquire方法,或者保存在entry中做条件等待。或者自己定义
* @return {@code true} if successful. Upon success, this object has
* been acquired.
* 如果成功返回true
* @throws IllegalMonitorStateException if acquiring would place this
* synchronizer in an illegal state. This exception must be
* thrown in a consistent fashion for synchronization to work
* correctly.
* @throws UnsupportedOperationException if exclusive mode is not supported
*/
//这是一个虚方法,需要由子类实现具体的功能
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
//ReentrantLock.java
static final class FairSync extends Sync {
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
* 递归、没有其他线程或者是第一个线程调用,即成功获取锁才返回true
*/
//acquires是调用lock方法通过acquire传的值
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
//AbstractQueuedSynchronizer中的state标记,使用compareAndSetState赋值
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");
//将state的值+acquires并赋给state
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、addWaiter
//如果能一次添加元素成功,直接返回。否则自旋直到添加成功
private Node addWaiter(Node mode) {
//构造Node,传入当前线程
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
//如果链表不为空
if (pred != null) {
node.prev = pred;
//如果插入链尾成功 直接返回
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
//插入队尾
private Node enq(final Node node) {
for (;;) {
Node t = tail;
//如果链表空 则新建一个head
//能进到这里 说明已经有其他线程正在占有锁,所以这个new Node()就代表那个占有锁的线程
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
//如果链表不为空,则一直尝试加入链表尾
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
3、acquireQueued
/**
* Acquires in exclusive uninterruptible mode for thread already in
* queue. Used by condition wait methods as well as acquire.
*
* @param node the node
* @param arg the acquire argument
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//p= node的前一个元素
final Node p = node.predecessor();
//如果前一个Node是head 说明前一条线程可能正在占有锁而且随时可能释放 此时当前线程去尝试获取锁
if (p == head && tryAcquire(arg)) {
//如果获取锁成功,将本线程所在节点置为队列头
setHead(node);
//将前一个节点的所有引用置为null,方便回收前一个节点
p.next = null; // help GC
failed = false;
return interrupted;
}
//判断是否需要阻塞,然后阻塞,并判断线程是否中断
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//定义在Node中waitStatus的状态值
//线程已经取消
static final int CANCELLED = 1;
//后续的线程需要唤醒
static final int SIGNAL = -1;
//线程正在等待
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/
static final int PROPAGATE = -3;
//pred=node.prev
//判断是否需要阻塞
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
* 如果这个node已经设置了一个请求释放的信号,可以安全的放置
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
//跳过前面设有取消标记的等待线程
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
* waitStatus是0或PROPAGATE,表明需要信号,但是又不想阻塞。调用者需要再次确认在阻塞之前不能获取锁
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
/**
* Convenience method to park and then check if interrupted
*
* @return {@code true} if interrupted
*/
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
//被唤醒后 判断线程是否被中断
return Thread.interrupted();
}
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
//调用park阻塞线程
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
//取消正在获取锁的尝试
private void cancelAcquire(Node node) {
// Ignore if node doesn't exist
if (node == null)
return;
node.thread = null;
// Skip cancelled predecessors
//跳过已经取消的线程元素
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
//
//pred的next元素不一定是node
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
// After this atomic step, other Nodes can skip past us.
// Before, we are free of interference from other threads.
//设置为取消状态,其他元素可以跳过这个元素
node.waitStatus = Node.CANCELLED;
// If we are the tail, remove ourselves.
//如果当前元素在末尾,直接删除
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
//如果其他元素需要SIGNAL标记,
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
//移除被标记为cancel的node前面的元素
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
//唤醒线程
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
//如果next元素为null或者状态是取消,
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);
}