下面来看ReentrantLock.unlock,尝试在当前锁的锁定计数即state值上减1,而lock每次把锁定计数加1,这也是为什么lock和unlock必须成对出现,否则锁定计数就不能正常恢复到0,其它线程就不能尝试获取锁
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
/**
* Attempts to release this lock.
*
* <p>If the current thread is the holder of this lock then the hold
* count is decremented. If the hold count is now zero then the lock
* is released. If the current thread is not the holder of this
* lock then { @link IllegalMonitorStateException} is thrown.
*
* @throws IllegalMonitorStateException if the current thread does not
* hold this lock
*/
public void unlock() {
sync.release( 1 );
}
* Attempts to release this lock.
*
* <p>If the current thread is the holder of this lock then the hold
* count is decremented. If the hold count is now zero then the lock
* is released. If the current thread is not the holder of this
* lock then { @link IllegalMonitorStateException} is thrown.
*
* @throws IllegalMonitorStateException if the current thread does not
* hold this lock
*/
public void unlock() {
sync.release( 1 );
}
AbstractQueuedsynchronizer.release(int arg) 方法会在锁定数目上减去arg,若新锁定数目为0,表示锁被当前线程释放, 则试图唤醒等待队列中的下一个线程。请注意这里仅是唤醒,而非把锁的所有权交给下一个线程。该线程能否成功获取锁,还要看运气。
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
/**
* Releases in exclusive mode. Implemented by unblocking one or
* more threads if { @link #tryRelease} returns true.
* This method can be used to implement method { @link Lock#unlock}.
*
* @param arg the release argument. This value is conveyed to
* { @link #tryRelease} but is otherwise uninterpreted and
* can represent anything you like.
* @return the value returned from { @link #tryRelease}
*/
public final boolean release( int arg) {
if (tryRelease(arg)) {
Node h = head;
/* head的waitStatus不为零表示它的后继在等待唤醒,
还记得AbstractQueuedSynchronizer.shouldParkAfterFailedAcquire中对waitStatus的操作么?waitStatus!=0表明或者处于CANCEL状态,或者是置SIGNAL表示下一个线程在等待其唤醒,CANCEL状态这里先不分析,可以认为这里!=0即表示SIGNAL状态 */
if (h != null && h.waitStatus != 0 )
unparkSuccessor(h);
return true ;
}
return false ;
}
* Releases in exclusive mode. Implemented by unblocking one or
* more threads if { @link #tryRelease} returns true.
* This method can be used to implement method { @link Lock#unlock}.
*
* @param arg the release argument. This value is conveyed to
* { @link #tryRelease} but is otherwise uninterpreted and
* can represent anything you like.
* @return the value returned from { @link #tryRelease}
*/
public final boolean release( int arg) {
if (tryRelease(arg)) {
Node h = head;
/* head的waitStatus不为零表示它的后继在等待唤醒,
还记得AbstractQueuedSynchronizer.shouldParkAfterFailedAcquire中对waitStatus的操作么?waitStatus!=0表明或者处于CANCEL状态,或者是置SIGNAL表示下一个线程在等待其唤醒,CANCEL状态这里先不分析,可以认为这里!=0即表示SIGNAL状态 */
if (h != null && h.waitStatus != 0 )
unparkSuccessor(h);
return true ;
}
return false ;
}
tryRelease定义在Sync类中
Sync.tryRelease会在当前锁定状态上减去要释放的锁定数,如果锁定状态为零则置当前持有锁线程为null,返回true,否则返回false
此外还会检查是否是占有锁的线程在调用,若不是则抛出IllegalMonitorStateException。
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
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;
}
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;
}
再来看unparkSuccessor
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
/**
* Wakes up node's successor, if one exists.
*
* @param node the node
*/
private void unparkSuccessor(Node node) {
/*
* Try to clear status in anticipation of signalling. It is
* OK if this fails or if status is changed by waiting thread.
*/
// 若当前节点waitStatus被置为SIGNAL则清零
compareAndSetWaitStatus(node, Node.SIGNAL, 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.
*/
// 若后续节点为空或已被cancel,则从尾部开始找到队列中第一个waitStatus<=0,即未被cancel的节点
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);
}
* Wakes up node's successor, if one exists.
*
* @param node the node
*/
private void unparkSuccessor(Node node) {
/*
* Try to clear status in anticipation of signalling. It is
* OK if this fails or if status is changed by waiting thread.
*/
// 若当前节点waitStatus被置为SIGNAL则清零
compareAndSetWaitStatus(node, Node.SIGNAL, 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.
*/
// 若后续节点为空或已被cancel,则从尾部开始找到队列中第一个waitStatus<=0,即未被cancel的节点
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);
}
再回头看AbstractQueuedSynchronizer.acquireQueued,注释1,2,3,4表明了在线程被唤醒后的执行顺序
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
/**
* 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) {
try {
boolean interrupted = false ;
for (;;) {
// 2 因为等待队列只会从尾部插入,所以在被唤醒节点和头节点之间不会新加入等待节点,只会有节点被cancel
// 3 如果被唤醒节点不是头节点的直接后续,由唤醒算法可以保证其和头结点之间没有waitStatus<=0的节点,但有可能有waitStatus大于0,即被CANCEL的节点,参见注释4
// 5获取锁成功则把当前节点设置为头节点,返回,否则线程继续被禁止,直到下一次被唤醒
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null ; // help GC
return interrupted;
}
// 1 被lock.release唤醒,parkAndCheckInterrupt返回false,继续回到for循环开始
// 4 被cancel的结点在shouldParkAfterFailedAcquire中会被清理掉,当前节点会成为头节点的直接后继,然后return false,在下次循环中即可尝试获取锁
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true ;
}
} catch (RuntimeException ex) {
cancelAcquire(node);
throw ex;
}
}
* 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) {
try {
boolean interrupted = false ;
for (;;) {
// 2 因为等待队列只会从尾部插入,所以在被唤醒节点和头节点之间不会新加入等待节点,只会有节点被cancel
// 3 如果被唤醒节点不是头节点的直接后续,由唤醒算法可以保证其和头结点之间没有waitStatus<=0的节点,但有可能有waitStatus大于0,即被CANCEL的节点,参见注释4
// 5获取锁成功则把当前节点设置为头节点,返回,否则线程继续被禁止,直到下一次被唤醒
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null ; // help GC
return interrupted;
}
// 1 被lock.release唤醒,parkAndCheckInterrupt返回false,继续回到for循环开始
// 4 被cancel的结点在shouldParkAfterFailedAcquire中会被清理掉,当前节点会成为头节点的直接后继,然后return false,在下次循环中即可尝试获取锁
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true ;
}
} catch (RuntimeException ex) {
cancelAcquire(node);
throw ex;
}
}