NonfairSync锁是重入锁的一种非公平锁,是指尝试获取锁的线程,如果失败则进入AQS锁等待队列中。在ReentaintLock类会默认创建一个非公平锁。
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
1.首先尝试将当前AQS 的state状态由0到1,如果修改成功则表明当前AQS的锁是0,没有别其他占用锁,并设置“ setExclusiveOwnerThread(Thread.currentThread());” 当前线程设置为持有锁的线程。如果设置失败则会调用AQS的 “ acquire(1);”方法。
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
2. accquire(1)方法会调用尝试获得锁失败并且已经加入AQS请求队列中,则会执行线程中断,表明自己已经被加入等待队列中。AQS的tryAcquire(arg)方法会调用NonfairSync中的tryAcquire(int acquires)方法。
/**
* Performs non-fair tryLock. tryAcquire is
* implemented in subclasses, but both need nonfair
* try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
3.首先获取当前线程和当前AQS中的状态(state)。如果AQS状态为0,则尝试一次CAS操作并把当前AQS的state设置为acquires,如果设置成功,则表明当前线程设置为持有锁的线程并返回true。
4.如果持有锁的线程是当前线程则将AQS状态值(state)增加acquires,设置成功则返回成功,否则返回失败表明获取锁失败。
5.addWaiter(Node mode)方法是将新建一个新的node添加到队列中,并返回此新建的节点。
/**
* Creates and enqueues node for current thread and given mode.
*
* @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
* @return the new node
*/
private Node addWaiter(Node mode) {
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;
}
6.首先获取当前的队列尾部的节点,如果尾节点不为空,这将新建的节点node添加到尾部节点并执行一次CAS操作将新建的节点设置为tail节点,如果成功则将返回此进行的节点。如果失败,则,执行enq(node);方法。
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
8.
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
7.死循环执行 首先获取tail节点,如果tail节点为空则进行一次CAS设置header节点初始化操作。然后设置tail节点为head节点。否则将新传递的节点设置为tail节点并返回。
8.acquireQueued(addWaiter(Node.EXCLUSIVE), arg)方法
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
9.进入方法是一个死循环 获取当前节点的前一个处理的节点,有且当前节点的前一个处理的节点是head节点并且尝试获取锁成功才返回的。设置head节点为当前节点并返回是中断状态。至此锁过程完毕。
二、释放锁
1.调用unlock方法进行释放锁实际上调用户AQS的release(arg)方法 如下:
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
2.首先会尝试释放锁,unparkSuccessor(h)方法释放成功后会将唤醒其他等待的线程node进行继续操作。
3.执行tryRelease(arg)方法如下
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;
}
4.首先获取AQS当前状态和要释放数量之差,判断如果当前线程不是当前锁所拥有的线程则会直接抛出异常。
5.如果之差为0说明完全释放成功。设置当前拥有的线程为空初始化AQS状态为0并返回true状态,否则设置AQS状态并返回false状态。