大纲
1.ReentractReadWriteLock的基本原理
2.基于AQS实现的ReentractReadWriteLock
3.ReentractReadWriteLock如何竞争写锁
4.ReentractReadWriteLock如何竞争读锁
5.ReentractReadWriteLock的公平锁和非公平锁
6.ReentrantReadWriteLock中的锁降级
7.Condition的说明介绍
8.Condition的源码实现
1.ReentractReadWriteLock的基本原理
(1)读锁和写锁关系
表面上读锁和写锁是两把锁,但实际上只是同一把锁的两个视图。读锁和写锁在初始化的时候会共用一个Sync,也就是同一把锁、两类线程。其中读线程和读线程不互斥,读线程和写线程互斥,写线程和写线程互斥。
(2)锁状态设计
和独占锁一样,读写锁也是使用state变量来表示锁的状态。只是将state变量拆成两半:高16位表示读锁状态,低16位表示写锁状态。
读写锁是通过位运算来快速确定读和写的状态的。假设当前state = s,则写状态等于s & ((1 << 16) - 1),读状态等于s >>> 16。当写状态增加1时,state = s + 1。当读状态加1时,state = s + (1 << 16)。
将一个int型的state变量拆成两半,而不是用两个int型变量分别表示读锁和写锁的状态,是因为无法用一次CAS同时操作两个int型变量。
1 << 0 等于 1,(1 << 0) - 1 = 0
1 << 1 等于 10,(1 << 1) - 1 = 01
1 << 2 等于 100,(1 << 2) - 1 = 011
1 << 4 等于 1000,(1 << 4) - 1 = 0111
1 << 8 等于 100000000,(1 << 8) - 1 = 011111111
1 << 16 等于 10000000000000000,(1 << 16) - 1 = 01111111111111111
//所以s & ((1 << 16) - 1)相当于将s的高16位全部抹去,只剩下低16位
//若s = 11111,则s >>> 2 = 00111
//所以s >>> 16,就是无符号补0右移16位
(3)写锁的获取与释放
写锁是一个可重入的排他锁,它只能被一个线程同时获取。如果当前线程已获取写锁,则增加写状态:s + 1。如果当前线程在获取写锁时,读锁已被获取或者自己不是已获写锁的线程,则进入等待状态。
(4)读锁的获取与释放
读锁是一个可重入的共享锁,它能被多个线程同时获取。在写状态为0时,读锁总会被成功获取,而所做的也只是增加读状态。如果当前线程已获取读锁,则增加读状态:state = s + (1 << 16)。如果当前线程在获取读锁时,写锁已被其他其他线程获取,则该线程进入等待状态。
2.基于AQS实现的ReentractReadWriteLock
(1)ReentractReadWriteLock的构造函数
(2)ReentractReadWriteLock的读锁和写锁
(3)ReentractReadWriteLock基于AQS的两对模版方法
(1)ReentractReadWriteLock的构造函数
readerLock变量表示读锁,writerLock变量表示写锁,sync变量表示公平锁还是非公平锁。
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
//Inner class providing readlock
private final ReentrantReadWriteLock.ReadLock readerLock;
//Inner class providing writelock
private final ReentrantReadWriteLock.WriteLock writerLock;
//Performs all synchronization mechanics
final Sync sync;
//Creates a new ReentrantReadWriteLock with default (nonfair) ordering properties.
public ReentrantReadWriteLock() {
this(false);
}
//Creates a new ReentrantReadWriteLock with the given fairness policy.
//@param fair {@code true} if this lock should use a fair ordering policy
public ReentrantReadWriteLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
//获取写锁
public ReentrantReadWriteLock.WriteLock writeLock() {
return writerLock;
}
//获取读锁
public ReentrantReadWriteLock.ReadLock readLock() {
return readerLock;
}
...
}
(2)ReentractReadWriteLock的读锁和写锁
读锁和写锁都会通过内部类Sync来实现获取锁和释放锁的功能。加写锁会调用AQS的acquire()方法,然后调用tryAcquire()方法。加读锁会调用AQS的acquireShared()方法,然后调用acquireShared()方法。
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
...
//Performs all synchronization mechanics
final Sync sync;
//The lock returned by method {@link ReentrantReadWriteLock#readLock}.
public static class ReadLock implements Lock, java.io.Serializable {
private final Sync sync;
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
//Acquires the read lock.
//Acquires the read lock if the write lock is not held by another thread and returns immediately.
//If the write lock is held by another thread then the current thread becomes disabled
//for thread scheduling purposes and lies dormant until the read lock has been acquired.
public void lock() {
sync.acquireShared(1);
}
//Acquires the read lock unless the current thread is Thread#interrupt interrupted.
public void lockInterruptibly() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//Acquires the read lock only if the write lock is not held by another thread at the time of invocation.
public boolean tryLock() {
return sync.tryReadLock();
}
//Acquires the read lock if the write lock is not held by another thread
//within the given waiting time and the current thread has not been Thread#interrupt interrupted.
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
//Attempts to release this lock.
//If the number of readers is now zero then the lock is made available for write lock attempts.
public void unlock() {
sync.releaseShared(1);
}
...
}
//The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
public static class WriteLock implements Lock, java.io.Serializable {
private final Sync sync;
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
//Acquires the write lock.
//Acquires the write lock if neither the read nor write lock are held by another thread and returns immediately,
//setting the write lock hold count to one.
//If the current thread already holds the write lock then the hold count is incremented by one and the method return immediately.
//If the lock is held by another thread then the current thread becomes disabled
//for thread scheduling purposes and lies dormant until the write lock has been acquired,
//at which time the write lock hold count is set to one.
public void lock() {
sync.acquire(1);
}
//Acquires the write lock unless the current thread is Thread#interrupt interrupted.
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
//Acquires the write lock only if it is not held by another thread at the time of invocation.
public boolean tryLock( ) {
return sync.tryWriteLock();
}
//Acquires the write lock if it is not held by another thread
//within the given waiting time and the current thread has not been Thread#interrupt interrupted.
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
//Attempts to release this lock.
//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 IllegalMonitorStateException is thrown.
public void unlock() {
sync.release(1);
}
...
}
...
}
(3)ReentractReadWriteLock基于AQS的两对模版方法
独占锁和读写锁的写锁都是基于AQS的acquire/release模版方法实现的,读写锁的读锁是基于AQS的acquireShared/releaseShared模版方法实现的。
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
//Acquires in exclusive mode, ignoring interrupts.
//Implemented by invoking at least once #tryAcquire, returning on success.
//Otherwise the thread is queued, possibly repeatedly blocking and unblocking, invoking #tryAcquire until success.
//This method can be used to implement method Lock#lock.
public final void acquire(int arg) {
//tryAcquire()需要子类重写
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
selfInterrupt();
}
}
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
//Releases in exclusive mode.
//Implemented by unblocking one or more threads if #tryRelease returns true.
//This method can be used to implement method Lock#unlock.
public final boolean release(int arg) {
//tryRelease()需要子类重写
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0) {
unparkSuccessor(h);
}
return true;
}
return false;
}
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
//Acquires in shared mode, ignoring interrupts.
//Implemented by first invoking at least once #tryAcquireShared, returning on success.
//Otherwise the thread is queued, possibly repeatedly blocking and unblocking, invoking #tryAcquireShared until success.
public final void acquireShared(int arg) {
//tryAcquireShared()需要子类重写
if (tryAcquireShared(arg) < 0) {
doAcquireShared(arg);
}
}
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
//Releases in shared mode.
//Implemented by unblocking one or more threads if #tryReleaseShared returns true.
public final boolean releaseShared(int arg) {
//tryReleaseShared()需要子类重写
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
...
}
3.ReentractReadWriteLock如何竞争写锁
(1)WriteLock的获取
(2)WriteLock的释放
(1)WriteLock的获取
WriteLock的lock()方法会调用AQS的acquire()模版方法来获取锁,而AQS的acquire()方法又会调用继承自AQS的Sync类的tryAcquire()方法。
在Sync类的tryAcquire()方法中,getState()方法会返回当前state变量的值。exclusiveCount()方法会从state变量中查找当前获得写锁的线程数量,writerShouldBlock()方法会判断当前写线程在抢占锁时是否应该阻塞。
情况一:c != 0 && w == 0
说明此时有线程持有读锁,所以当前线程获取不到写锁,返回false。由此可见,一个线程获取读锁后不能再继续重入获取写锁(不能锁升级)。但从后续可知,一个线程获取写锁后可以再继续重入获取读锁(能锁降级)。
情况二:c != 0 && w != 0
说明此时有线程持有写锁且不可能有线程持有读锁,所以需要判断持有写锁的线程是否是当前线程自己,如果不是则返回false。
情况三:c != 0 && w != 0 && current持有锁
说明此时当前线程正在持有写锁,属于重入写锁的情况,需要判断重入次数,锁重入的次数不能大于65535。
情况四:c == 0
说明此时没有线程持有锁,所以当前线程可以通过CAS操作抢占锁。
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
...
//Performs all synchronization mechanics
final Sync sync;
//The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
public static class WriteLock implements Lock, java.io.Serializable {
private final Sync sync;
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
//Acquires the write lock.
//Acquires the write lock if neither the read nor write lock are held by another thread and returns immediately,
//setting the write lock hold count to one.
//If the current thread already holds the write lock then the hold count is incremented by one and the method return immediately.
//If the lock is held by another thread then the current thread becomes disabled
//for thread scheduling purposes and lies dormant until the write lock has been acquired,
//at which time the write lock hold count is set to one.
public void lock() {
//执行AQS的acquire()模版方法,获取写锁(独占锁)
sync.acquire(1);
}
...
}
//Synchronization implementation for ReentrantReadWriteLock.
//Subclassed into fair and nonfair versions.
abstract static class Sync extends AbstractQueuedSynchronizer {
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
//Returns the number of exclusive holds represented in count
static int exclusiveCount(int c) {
//获取写锁状态:c & ((1 << 16) - 1)
//也就是从state变量中查找当前获得写锁的线程数量
return c & EXCLUSIVE_MASK;
}
//获取写锁(独占锁)
protected final boolean tryAcquire(int acquires) {
//Walkthrough:
//1.If read count nonzero or write count nonzero and owner is a different thread, fail.
//2.If count would saturate, fail. (This can only happen if count is already nonzero.)
//3. Otherwise, this thread is eligible for lock if it is either a reentrant acquire or queue policy allows it.
//If so, update state and set owner.
Thread current = Thread.currentThread();
int c = getState();//获取锁的状态
int w = exclusiveCount(c);//获取写锁的状态
if (c != 0) {
//如果c != 0 && w == 0时,说明有线程持有读锁,所以当前获取写锁的线程会被阻塞,会返回false
//如果c != 0 && w != 0 && current没获取锁,说明有其他线程持有写锁(不可能有线程持有读锁),所以当前获取写锁的线程会被阻塞,会返回false
if (w == 0 || current != getExclusiveOwnerThread()) {
return false;
}
//判断重入次数不能大于65535
if (w + exclusiveCount(acquires) > MAX_COUNT) {
throw new Error("Maximum lock count exceeded");
}
//Reentrant acquire
setState(c + acquires);
return true;
}
//此时c == 0,说明没有线程持有锁,可以通过CAS操作抢占锁
if (writerShouldBlock() || !compareAndSetState(c, c + acquires)) {
return false;
}
setExclusiveOwnerThread(current);
return true;
}
...
}
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
//获取写锁(独占锁)
//Acquires in exclusive mode, ignoring interrupts.
//Implemented by invoking at least once #tryAcquire, returning on success.
//Otherwise the thread is queued, possibly repeatedly blocking and unblocking, invoking #tryAcquire until success.
//This method can be used to implement method Lock#lock.
public final void acquire(int arg) {
//tryAcquire()需要子类重写,此时执行ReentrantReadWriteLock的内部类Sync的tryAcquire()方法
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
selfInterrupt();
}
}
...
}
(2)WriteLock的释放
WriteLock的unlock()方法会调用AQS的release()模版方法来释放锁,而AQS的release()方法又会调用继承自AQS的Sync类的tryRelease()方法。
在Sync类的tryRelease()方法中,首先通过getState() - releases来递减写锁的次数。由于写锁的重入次数保存在低位,所以直接十进制相减即可。然后通过exclusiveCount()获取写锁的重入次数,如果为0说明锁释放成功。最后通过setState()方法修改state变量的值。由于写锁是独占锁,所以设置state变量的值不需要CAS操作。
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
...
//Performs all synchronization mechanics
final Sync sync;
//The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
public static class WriteLock implements Lock, java.io.Serializable {
private final Sync sync;
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
//Attempts to release this lock.
//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 IllegalMonitorStateException is thrown.
public void unlock() {
//执行AQS的release()方法,释放写锁(独占锁)
sync.release(1);
}
...
}
//Synchronization implementation for ReentrantReadWriteLock.
//Subclassed into fair and nonfair versions.
abstract static class Sync extends AbstractQueuedSynchronizer {
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
//Returns the number of exclusive holds represented in count
static int exclusiveCount(int c) {
//获取写锁状态:c & ((1 << 16) - 1)
//也就是从state变量中查找当前获得写锁的线程数量
return c & EXCLUSIVE_MASK;
}
//Note that tryRelease and tryAcquire can be called by Conditions.
//So it is possible that their arguments contain both read and write holds
//that are all released during a condition wait and re-established in tryAcquire.
protected final boolean tryRelease(int releases) {
if (!isHeldExclusively()) {
throw new IllegalMonitorStateException();
}
int nextc = getState() - releases;//递减写锁的次数
boolean free = exclusiveCount(nextc) == 0;//计算写锁的重入次数
if (free) {
setExclusiveOwnerThread(null);
}
setState(nextc);
return free;
}
...
}
...
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
//释放写锁(独占锁)
//Releases in exclusive mode.
//Implemented by unblocking one or more threads if #tryRelease returns true.
//This method can be used to implement method Lock#unlock.
public final boolean release(int arg) {
//tryRelease()需要子类重写,此时执行ReentrantReadWriteLock的内部类Sync的tryRelease()方法
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0) {
unparkSuccessor(h);
}
return true;
}
return false;
}
...
}
4.ReentractReadWriteLock如何竞争读锁
(1)ReadLock的获取
(2)ReadLock的释放
(3)fullTryAcquireShared()方法
(1)ReadLock的获取
ReadLock的lock()方法会调用AQS的acquireShared()模版方法来获取读锁,而AQS的acquireShared()方法又会调用Sync类的tryAcquireShared()方法。
在继承自AQS的Sync类的tryAcquireShared()方法中:首先会判断是否有线程持有写锁 + 持有写锁的线程是否是当前线程。如果有线程持有写锁,但不是当前线程持有写锁,那么会阻塞当前线程。然后判断当前线程获取读锁是否应该阻塞,读锁重入次数是否小于65535,以及通过CAS修改state值来抢占读锁是否成功。
如果当前线程获取读锁不应该被阻塞,读锁重入次数也小于65535,且CAS抢占读锁也成功,那么就使用ThreadLocal记录线程重入读锁的次数。否则,就继续调用fullTryAcquireShared()方法通过自旋尝试获取锁。
如果调用Sync的tryAcquireShared()方法返回-1,则调用AQS的doAcquireShared()方法入队等待队列和阻塞当前线程。
在等待队列中,如果等待获取读锁的线程被唤醒,那么会继续循环把其后连续的所有等待获取读锁的线程都唤醒,直到遇到一个等待获取写锁的线程为止。
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
...
//Performs all synchronization mechanics
final Sync sync;
//The lock returned by method {@link ReentrantReadWriteLock#readLock}.
public static class ReadLock implements Lock, java.io.Serializable {
private final Sync sync;
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
//Acquires the read lock.
//Acquires the read lock if the write lock is not held by another thread and returns immediately.
//If the write lock is held by another thread then the current thread becomes disabled
//for thread scheduling purposes and lies dormant until the read lock has been acquired.
public void lock() {
//执行AQS的acquireShared()方法,获取读锁(共享锁)
sync.acquireShared(1);
}
...
}
//Synchronization implementation for ReentrantReadWriteLock.
//Subclassed into fair and nonfair versions.
abstract static class Sync extends AbstractQueuedSynchronizer {
static final int SHARED_SHIFT = 16;
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
//Returns the number of exclusive holds represented in count
static int exclusiveCount(int c) {
//获取写锁状态:c & ((1 << 16) - 1)
//也就是从state变量中查找当前获得写锁的线程数量
return c & EXCLUSIVE_MASK;
}
//Returns the number of shared holds represented in count
static int sharedCount(int c) {
//获取读锁状态:c >>> 16
//也就是从state变量中查找当前获得读锁的线程数量
return c >>> SHARED_SHIFT;
}
//A counter for per-thread read hold counts.
//Maintained as a ThreadLocal; cached in cachedHoldCounter
static final class HoldCounter {
int count = 0;
//Use id, not reference, to avoid garbage retention
final long tid = getThreadId(Thread.currentThread());
}
//ThreadLocal subclass. Easiest to explicitly define for sake of deserialization mechanics.
static final class ThreadLocalHoldCounter extends ThreadLocal<HoldCounter> {
public HoldCounter initialValue() {
return new HoldCounter();
}
}
//The number of reentrant read locks held by current thread.
//Initialized only in constructor and readObject.
//Removed whenever a thread's read hold count drops to 0.
private transient ThreadLocalHoldCounter readHolds;
//The hold count of the last thread to successfully acquire readLock.
//This saves ThreadLocal lookup in the common case where the next thread to release is the last one to acquire.
//This is non-volatile since it is just used as a heuristic, and would be great for threads to cache.
private transient HoldCounter cachedHoldCounter;
//firstReader is the first thread to have acquired the read lock.
//firstReaderHoldCount is firstReader's hold count.
private transient Thread firstReader = null;
private transient int firstReaderHoldCount;
Sync() {
readHolds = new ThreadLocalHoldCounter();
setState(getState());// ensures visibility of readHolds
}
//获取读锁(共享锁)
protected final int tryAcquireShared(int unused) {
//Walkthrough:
//1.If write lock held by another thread, fail.
//2.Otherwise, this thread is eligible for lock wrt state,
//so ask if it should block because of queue policy.
//If not, try to grant by CASing state and updating count.
//Note that step does not check for reentrant acquires,
//which is postponed to full version to avoid having to check hold count in the more typical non-reentrant case.
//3.If step 2 fails either because thread apparently not eligible or CAS fails or count saturated,
//chain to version with full retry loop.
Thread current = Thread.currentThread();
int c = getState();
//如果写锁的持有线程不是当前线程,则直接阻塞
//从而说明,如果一个线程先获取了写锁,那么是可以重入获取读锁的
if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current) {
return -1;
}
int r = sharedCount(c);//获取读锁的状态
//首先判断当前线程获取读锁是否应该阻塞,然后判断读锁重入次数是否小于65535,最后通过CAS修改state值抢占读锁
if (!readerShouldBlock() && r < MAX_COUNT && compareAndSetState(c, c + SHARED_UNIT)) {
//使用ThreadLocal记录每个线程重入读锁的次数
if (r == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) {
cachedHoldCounter = rh = readHolds.get();
} else if (rh.count == 0) {
readHolds.set(rh);
}
rh.count++;
}
return 1;
}
//如果当前线程获取读锁失败,则调用fullTryAcquireShared()方法通过自旋尝试获取锁
return fullTryAcquireShared(current);
}
...
}
...
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
//获取读锁(共享锁)
//Acquires in shared mode, ignoring interrupts.
//Implemented by first invoking at least once #tryAcquireShared, returning on success.
//Otherwise the thread is queued, possibly repeatedly blocking and unblocking, invoking #tryAcquireShared until success.
public final void acquireShared(int arg) {
//tryAcquireShared()需要子类重写,此时执行ReentrantReadWriteLock的内部类Sync的tryAcquireShared()方法
if (tryAcquireShared(arg) < 0) {
//调用AQS的doAcquireShared()方法入队等待队列和阻塞当前线程
doAcquireShared(arg);
}
}
//Acquires in shared uninterruptible mode.
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head) {
//注意:如果等待获取读锁的线程被唤醒,那么会继续循环把其后连续的所有等待获取读锁的线程都唤醒
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
if (interrupted) {
selfInterrupt();
}
failed = false;
return;
}
}
//执行shouldParkAfterFailedAcquire()方法设置node结点的前驱结点的状态为SIGNAL
//执行parkAndCheckInterrupt()方法挂起当前线程
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
interrupted = true;
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}
...
}
(2)ReadLock的释放
ReadLock的unlock()方法会调用AQS的releaseShared()模版方法来释放锁,而AQS的releaseShared()方法又会调用Sync类的tryReleaseShared()方法。
在Sync类的tryReleaseShared()方法中:首先会结合ThreadLocal处理当前线程重入读锁的次数,然后再通过自旋 + CAS设置state值来实现释放读锁,最后执行AQS的doReleaseShared()方法唤醒阻塞的线程。
tryRelease()和tryReleaseShared()的区别:读锁是共享锁,由多个线程持有,所以释放读锁需要通过自旋 + CAS完成。写锁是独占锁,由单个线程持有,所以释放写锁时不需要CAS操作。
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
...
//Performs all synchronization mechanics
final Sync sync;
//The lock returned by method {@link ReentrantReadWriteLock#readLock}.
public static class ReadLock implements Lock, java.io.Serializable {
private final Sync sync;
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
//Attempts to release this lock.
//If the number of readers is now zero then the lock is made available for write lock attempts.
public void unlock() {
//执行AQS的releaseShared()方法,释放读锁(共享锁)
sync.releaseShared(1);
}
...
}
//Synchronization implementation for ReentrantReadWriteLock.
//Subclassed into fair and nonfair versions.
abstract static class Sync extends AbstractQueuedSynchronizer {
...
//释放读锁(共享锁)
protected final boolean tryReleaseShared(int unused) {
Thread current = Thread.currentThread();
//首先结合ThreadLocal处理当前线程重入读锁的次数
if (firstReader == current) {
if (firstReaderHoldCount == 1) {
firstReader = null;
} else {
firstReaderHoldCount--;
}
} else {
HoldCounter rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) {
rh = readHolds.get();
}
int count = rh.count;
if (count <= 1) {
readHolds.remove();
if (count <= 0) {
throw unmatchedUnlockException();
}
}
--rh.count;
}
//然后通过自旋 + CAS设置state值来实现释放读锁
for (;;) {
int c = getState();
int nextc = c - SHARED_UNIT;
if (compareAndSetState(c, nextc)) {
//Releasing the read lock has no effect on readers,
//but it may allow waiting writers to proceed if both read and write locks are now free.
return nextc == 0;
}
}
}
...
}
...
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
//释放读锁(共享锁)
//Releases in shared mode.
//Implemented by unblocking one or more threads if #tryReleaseShared returns true.
public final boolean releaseShared(int arg) {
//tryReleaseShared()需要子类重写,此时执行ReentrantReadWriteLock的内部类Sync的tryReleaseShared()方法
if (tryReleaseShared(arg)) {
//执行AQS的doReleaseShared()方法唤醒阻塞的线程
doReleaseShared();
return true;
}
return false;
}
//Release action for shared mode -- signals successor and ensures propagation.
//Note: For exclusive mode, release just amounts to calling unparkSuccessor of head if it needs signal.
private void doReleaseShared() {
//Ensure that a release propagates, even if there are other in-progress acquires/releases.
//This proceeds in the usual way of trying to unparkSuccessor of head if it needs signal.
//But if it does not, status is set to PROPAGATE to ensure that upon release, propagation continues.
//Additionally, we must loop in case a new node is added while we are doing this.
//Also, unlike other uses of unparkSuccessor, we need to know if CAS to reset status fails, if so rechecking.
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) {
//loop to recheck cases
continue;
}
//执行AQS的unparkSuccessor()方法
unparkSuccessor(h);
} else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) {
//loop on failed CAS
continue;
}
}
//loop if head changed
if (h == head) {
break;
}
}
}
//Wakes up node's successor, if one exists.
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.
//Node结点的状态watiStatus可以分为如下几种:
//默认(0)、CANCELED(1)、SIGNAL(-1)、CONDITION(-2)、PROPAGATE(-3)
//默认情况下,watiStatus应该是0,或者是空
//获得头结点的状态
int ws = node.waitStatus;
//需要设置头结点的状态为0
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;
//如果头结点的后继结点为null或其状态为CANCELED
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);
}
}
...
}
(3)fullTryAcquireShared()方法
在如下两种情况下,该方法会返回-1让当前线程加入等待队列进行等待。
情况一:此时有线程获得了写锁但不是当前线程获得写锁后重入读锁。
情况二:readerShouldBlock()方法返回true且不是重入读锁。
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
...
//Synchronization implementation for ReentrantReadWriteLock.
//Subclassed into fair and nonfair versions.
abstract static class Sync extends AbstractQueuedSynchronizer {
static final int SHARED_SHIFT = 16;
static final int SHARED_UNIT = (1 << SHARED_SHIFT);
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
//Returns the number of exclusive holds represented in count
static int exclusiveCount(int c) {
//获取写锁状态:c & ((1 << 16) - 1)
//也就是从state变量中查找当前获得写锁的线程数量
return c & EXCLUSIVE_MASK;
}
//Returns the number of shared holds represented in count
static int sharedCount(int c) {
//获取读锁状态:c >>> 16
//也就是从state变量中查找当前获得读锁的线程数量
return c >>> SHARED_SHIFT;
}
//A counter for per-thread read hold counts.
//Maintained as a ThreadLocal; cached in cachedHoldCounter
static final class HoldCounter {
int count = 0;
//Use id, not reference, to avoid garbage retention
final long tid = getThreadId(Thread.currentThread());
}
//ThreadLocal subclass. Easiest to explicitly define for sake of deserialization mechanics.
static final class ThreadLocalHoldCounter extends ThreadLocal<HoldCounter> {
public HoldCounter initialValue() {
return new HoldCounter();
}
}
//The number of reentrant read locks held by current thread.
//Initialized only in constructor and readObject.
//Removed whenever a thread's read hold count drops to 0.
private transient ThreadLocalHoldCounter readHolds;
//The hold count of the last thread to successfully acquire readLock.
//This saves ThreadLocal lookup in the common case where the next thread to release is the last one to acquire.
//This is non-volatile since it is just used as a heuristic, and would be great for threads to cache.
private transient HoldCounter cachedHoldCounter;
//firstReader is the first thread to have acquired the read lock.
//firstReaderHoldCount is firstReader's hold count.
private transient Thread firstReader = null;
private transient int firstReaderHoldCount;
Sync() {
readHolds = new ThreadLocalHoldCounter();
setState(getState());// ensures visibility of readHolds
}
...
//Full version of acquire for reads,
//that handles CAS misses and reentrant reads not dealt with in tryAcquireShared.
final int fullTryAcquireShared(Thread current) {
//This code is in part redundant with that in tryAcquireShared
//but is simpler overall by not complicating tryAcquireShared with interactions
//between retries and lazily reading hold counts.
HoldCounter rh = null;
for (;;) {
int c = getState();
if (exclusiveCount(c) != 0) {
//如果当前有其他线程获取到写锁,那么返回-1,当前线程会挂起阻塞并进入等待队列
if (getExclusiveOwnerThread() != current) {
return -1;
}
//else we hold the exclusive lock; blocking here would cause deadlock.
} else if (readerShouldBlock()) {
//如果readerShouldBlock()返回true,表示当前线程获取读锁需要被阻塞
//结合ThreadLocal处理当前线程重入读锁的次数
//Make sure we're not acquiring read lock reentrantly
if (firstReader == current) {
//assert firstReaderHoldCount > 0;
} else {
if (rh == null) {
rh = cachedHoldCounter;
if (rh == null || rh.tid != getThreadId(current)) {
rh = readHolds.get();
if (rh.count == 0) {
readHolds.remove();
}
}
}
//如果不是重入
if (rh.count == 0) {
return -1;
}
}
}
if (sharedCount(c) == MAX_COUNT) {
throw new Error("Maximum lock count exceeded");
}
if (compareAndSetState(c, c + SHARED_UNIT)) {
//结合ThreadLocal处理当前线程重入读锁的次数
if (sharedCount(c) == 0) {
firstReader = current;
firstReaderHoldCount = 1;
} else if (firstReader == current) {
firstReaderHoldCount++;
} else {
if (rh == null) {
rh = cachedHoldCounter;
}
if (rh == null || rh.tid != getThreadId(current)) {
rh = readHolds.get();
} else if (rh.count == 0) {
readHolds.set(rh);
}
rh.count++;
cachedHoldCounter = rh; // cache for release
}
return 1;
}
}
}
...
}
...
}
5.ReentractReadWriteLock的公平锁和非公平锁
(1)公平锁的实现代码
(2)非公平锁的实现代码
(1)公平锁的实现代码
对公平锁来说,用于判断读线程在抢占锁时是否应该阻塞的readerShouldBlock()方法,以及用于判断写线程在抢占锁时是否应该阻塞的writerShouldBlock()方法,都会通过hasQueuedPredecessors()方法判断当前队列中是否有线程排队。只要队列中有其他线程在排队,写线程和读线程都要排队尾,不能抢占锁。
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
...
//Fair version of Sync
static final class FairSync extends Sync {
final boolean writerShouldBlock() {
return hasQueuedPredecessors();
}
final boolean readerShouldBlock() {
return hasQueuedPredecessors();
}
}
//Synchronization implementation for ReentrantReadWriteLock.
//Subclassed into fair and nonfair versions.
abstract static class Sync extends AbstractQueuedSynchronizer {
...
//Returns true if the current thread, when trying to acquire the read lock,
//and otherwise eligible to do so, should block because of policy for overtaking other waiting threads.
abstract boolean readerShouldBlock();
//Returns true if the current thread, when trying to acquire the write lock,
//and otherwise eligible to do so, should block because of policy for overtaking other waiting threads.
abstract boolean writerShouldBlock();
...
}
...
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
//Queries whether any threads have been waiting to acquire longer than the current thread.
//判断当前队列中是否有线程排队
public final boolean hasQueuedPredecessors() {
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
//所以!hasQueuedPredecessors() 等价于:
//h == t || (h.next != null && h.next.thread == Thread.currentThread())
return h != t && ((s = h.next) == null || s.thread != Thread.currentThread());
}
...
}
(2)非公平锁的实现代码
对非公平锁来说,writerShouldBlock()方法会直接返回false,因为写线程可以去抢非公平锁的情况一定是:没有其他线程持有锁或者是线程自己重入写锁,所以不需要阻塞。而readerShouldBlock()方法会调用一个方法来决定是否阻塞读线程,在一定程度上避免发生写锁无限等待的问题(死锁饥饿问题)。
readerShouldBlock()方法调用的这个方法就是AQS的apparentlyFirstQueuedIsExclusive()方法。如果当前等待队列头结点的后继结点是写锁结点,那么该方法就返回true,表示当前来获取读锁的读线程需要排队。如果当前等待队列头结点的后继结点是读锁结点,那么该方法就返回false,表示当前来获取读锁的读线程可以抢占锁。
由于读线程和读线程是不互斥的,如果当前正在有线程持有读锁,而新来的读线程还非公平地抢读锁,可能导致写线程永远拿不到写锁。
public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
...
static final class NonfairSync extends Sync {
//写线程调用
final boolean writerShouldBlock() {
return false; // writers can always barge
}
//读线程调用
final boolean readerShouldBlock() {
//As a heuristic to avoid indefinite writer starvation,
//block if the thread that momentarily appears to be head of queue, if one exists, is a waiting writer.
//This is only a probabilistic effect since a new reader will not block
//if there is a waiting writer behind other enabled readers that have not yet drained from the queue.
return apparentlyFirstQueuedIsExclusive();
}
}
...
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
//如果当前等待队列头结点的后继结点是写锁结点,那么该方法就返回true,表示当前来获取读锁的读线程需要排队;
//如果当前等待队列头结点的后继结点是读锁结点,那么该方法就返回false,表示当前来获取读锁的读线程可以抢占锁;
final boolean apparentlyFirstQueuedIsExclusive() {
Node h, s;
return (h = head) != null &&
(s = h.next) != null &&
!s.isShared() &&
s.thread != null;
}
...
}
6.ReentrantReadWriteLock中的锁降级
(1)什么是ReentrantReadWriteLock中的锁降级
(2)ReentrantReadWriteLock中的锁降级例子
(1)什么是ReentrantReadWriteLock中的锁降级
这里的锁降级,指的是从写锁降级到读锁。也就是如果线程A获取了写锁,在写锁没有释放的情况下允许再去获取读锁。如果线程A获取了写锁,然后释放写锁,之后再获取读锁,这就不是锁降级。当然如果线程A获取了读锁,在读锁没有释放的情况下是不允许再获取写锁。
(2)ReentrantReadWriteLock中的锁降级例子
锁降级是为了提升性能。如果只使用写锁,那么长时间执行use(data)读数据时会阻塞其他读线程。所以通过将写锁降级为读锁,那么执行use(data)时也不会阻塞读线程。
Object data;
public void processData() {
readLock.lock();//要先获取读锁,因为后面要读数据,比如update为true时,需要
if (!update) {//发现要进行修改
readLock.unlock();//必须先释放读锁,接下来才能获取写锁
writeLock.lock();//锁降级从这里获取到写锁开始
try {
if (!update) {
//准备修改数据,写数据data
data = ...;
update = true;
}
readLock.lock();//在获得写锁的基础上,继续获取读锁
} finally {
writeLock.unlock();//释放写锁,写锁降级为读锁,完成锁降级
}
}
try {
//使用数据,读数据data使用时间长
use(data);
} finally {
readLock.unlock();//释放读锁
}
}
7.Condition的说明介绍
(1)Condition接口
(2)Condition说明
(1)Condition接口
public interface Condition {
//Causes the current thread to wait until it is signalled or Thread#interrupt interrupted.
void await() throws InterruptedException;
//Causes the current thread to wait until it is signalled.
void awaitUninterruptibly();
//Causes the current thread to wait until it is signalled or interrupted, or the specified waiting time elapses.
long awaitNanos(long nanosTimeout) throws InterruptedException;
//Causes the current thread to wait until it is signalled or interrupted, or the specified waiting time elapses.
boolean await(long time, TimeUnit unit) throws InterruptedException;
//Causes the current thread to wait until it is signalled or interrupted, or the specified deadline elapses.
boolean awaitUntil(Date deadline) throws InterruptedException;
//Wakes up one waiting thread.
void signal();
//Wakes up all waiting threads.
void signalAll();
}
(2)Condition说明
一.Condition与wait/notify的对比
Condition的功能和wait/notify类似,可以实现等待/通知模式。wait/notify必须要和synchronized一起使用,Condition也必须要和Lock一起使用。Condition避免了wait/notify的生产者通知生产者,消费者通知消费者的问题。
二.Condition的使用
一般都会将Condition对象作为成员变量。当调用Condition的await()方法后,当前线程会释放锁并挂起等待。当其他线程线程调用Condition的signal()方法通知当前线程(释放锁)后,当前线程才会从Condition的await()方法处返回,并且返回的时候已经获得了锁。
三.两个线程在使用Condition的交互流程
线程1 -> 获取锁 -> 释放锁 + await()阻塞等待 ->
线程2 -> 获取锁 -> signal()唤醒线程1 + 释放锁 ->
线程1 -> 被唤醒 + 尝试获取锁 -> 释放锁
四.读写锁和独占锁是否支持Condition
独占锁和读写锁的写锁都支持Condition,但是读写锁的读锁是不支持Condition的。
ReentrantLock支持Condition。
ReentrantReadWriteLock的WriteLock支持Condition。
五.由AQS的内部类ConditionObject实现
每个Condition对象都有一个Condition队列,这个队列是Condition对象实现等待/通知功能的关键。
六.Condition的应用场景
LinkedBlockingQueue、ArrayBlockQueue、CyclicBarrier都用到了Condition来实现线程等待。
public class ConditionDemo() {
static ReentrantLock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
public static void main(String[] args) throws Exception {
new Thread() {
public void run() {
lock.lock();
System.out.println("第一个线程加锁");
try {
System.out.println("第一个线程释放锁以及阻塞等待");
condition.await();
System.out.println("第一个线程重新获取锁");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("第一个线程释放锁");
lock.unlock();
};
}.start();
Thread.sleep(3000);
new Thread() {
public void run() {
lock.lock();
System.out.println("第二个线程加锁");
System.out.println("第二个线程唤醒第一个线程");
condition.signal();
lock.unlock();
System.out.println("第二个线程释放锁");
};
}.start();
}
}
8.Condition的源码实现
(1)创建ConditionObject对象
(2)ConditionObject的Condition队列
(3)ConditionObject的等待方法await()
(4)ConditionObject的通知方法signal()
(1)创建ConditionObject对象
调用ReentrantLock的newCondition()方法可以创建一个Condition对象,ReentrantLock的newCondition()方法会调用Sync的newCondition()方法,而Sync的newCondition()方法会创建ConditionObject对象。
public class ReentrantLock implements Lock, java.io.Serializable {
...
//Synchronizer providing all implementation mechanics
private final Sync sync;
//Returns a {@link Condition} instance for use with this Lock instance.
public Condition newCondition() {
//执行ReentrantLock内部类Sync的newCondition()方法
return sync.newCondition();
}
//Base of synchronization control for this lock.
//Subclassed into fair and nonfair versions below.
//Uses AQS state to represent the number of holds on the lock.
abstract static class Sync extends AbstractQueuedSynchronizer {
...
final ConditionObject newCondition() {
return new ConditionObject();
}
...
}
...
}
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
public class ConditionObject implements Condition, java.io.Serializable {
//First node of condition queue.
private transient Node firstWaiter;
//Last node of condition queue.
private transient Node lastWaiter;
//Creates a new ConditionObject instance.
public ConditionObject() {
}
...
}
...
}
(2)ConditionObject的Condition队列
在ConditionObject对象中,会有一个Condition队列,ConditionObject对象维护的Condition队列是一个单向链表。
ConditionObject对象的属性firstWaiter和lastWaiter代表队列的头尾结点。当线程调用await()方法时,该线程就会被封装成Node结点。然后该Node结点就会被作为新增结点加入到Condition队列的尾部。
由于Condition对象拥有Condition队列的头尾结点的引用,所以只需将原来尾结点的nextWaiter指向新增结点,并更新尾结点即可。这个更新过程无须使用CAS保证,因为调用await()方法的线程已经获取锁了。
(3)ConditionObject的等待方法await()
ConditionObject的await()方法的主要逻辑:
一.通过addConditionWaiter()方法将当前线程添加到Condition队列
二.通过fullyRelease()方法释放锁
三.通过LockSupport.park()方法挂起当前线程
四.被signal()方法唤醒后,通过acquireQueued()方法尝试获取锁
其实相当于将等待队列的头结点(获取了锁的结点)移动到Condition队列中。但等待队列的头结点不会直接加入Condition队列,而是会把当前线程封装成一个新的Node结点加入到Condition队列尾部。
**注意:**调用await()方法的线程其实已成功获取锁,该线程对应等待队列的头结点。await()方法会将当前线程封装成结点并加入到Condition队列,然后释放锁,并唤醒等待队列头结点的后继结点对应线程,再挂起当前线程进入等待状态。当该线程被signal()方法唤醒后,便会通过acquireQueued()方法尝试获取锁。所以调用await()方法的线程在阻塞后被唤醒,也有可能获取锁失败继续阻塞。
**Condition.await()原理总结:**将自己加入Condition队列、释放锁、挂起自己。
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
public class ConditionObject implements Condition, java.io.Serializable {
//First node of condition queue.
private transient Node firstWaiter;
//Last node of condition queue.
private transient Node lastWaiter;
...
//Implements interruptible condition wait.
//If current thread is interrupted, throw InterruptedException.
public final void await() throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
//1.执行ConditionObject的addConditionWaiter()方法,将当前线程封装成Node结点并加入Condition队列
Node node = addConditionWaiter();
//2.调用AQS的fullyRelease()方法释放锁
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
//3.阻塞当前线程
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) {
break;
}
}
//4.当前线程被signal()方法唤醒后,执行AQS的acquireQueued()方法尝试获取锁
if (acquireQueued(node, savedState) && interruptMode != THROW_IE) {
interruptMode = REINTERRUPT;
}
if (node.nextWaiter != null) {// clean up if cancelled
unlinkCancelledWaiters();
}
if (interruptMode != 0) {
reportInterruptAfterWait(interruptMode);
}
}
//将当前线程封装成Node结点并加入Condition队列
private Node addConditionWaiter() {
Node t = lastWaiter;
//If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null) {
firstWaiter = node;
} else {
t.nextWaiter = node;
}
lastWaiter = node;
return node;
}
...
}
//释放锁
//Invokes release with current state value; returns saved state.
//Cancels node and throws exception on failure.
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed) {
node.waitStatus = Node.CANCELLED;
}
}
}
//Releases in exclusive mode.
//Implemented by unblocking one or more threads if #tryRelease returns true.
//This method can be used to implement method Lock#unlock.
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0) {
//唤醒等待队列头结点的后继结点
unparkSuccessor(h);
}
return true;
}
return false;
}
//Acquires in exclusive uninterruptible mode for thread already in queue.
//Used by condition wait methods as well as acquire.
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;
}
//执行shouldParkAfterFailedAcquire()方法设置node结点的前驱结点的状态为SIGNAL
//执行parkAndCheckInterrupt()方法挂起当前线程
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
interrupted = true;
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}
...
}
(4)ConditionObject的通知方法signal()
ConditionObject的signal()方法的主要逻辑:
一.首先从Condition队列中取出等待时间最长的结点,也就是first结点
二.然后将等待时间最长的结点(first结点)转移到AQS的等待队列(CLH队列)中
三.最后唤醒该first结点对应的线程
由于该first结点对应的线程在await()方法中加入Condition队列后被阻塞,所以该first结点对应的线程在被唤醒后,会回到await()方法中继续执行,也就是会执行AQS的acquireQueued()方法去尝试获取锁。
调用signal()方法的前提条件是当前线程必须获得了锁,所以signal()方法首先会检查当前线程是否获取了锁,接着才去获取Condition队列的first结点,然后才将first结点移动到等待队列,并唤醒该first结点对应的线程。
通过调用AQS的enq()方法,Condition队列的first结点会添加到等待队列。当first结点被移动到等待队列后,再唤醒first结点对应的线程尝试获取锁。
被唤醒的first结点对应的线程,将从await()方法中的while循环退出。因为已经在等待队列中,所以isOnSyncQueue()方法会返回true,从而会调用AQS的acquireQueued()方法来竞争获取锁。
**Condition.signal()原理总结:**把Condition队列中的头结点,转化为等待队列中的尾结点。
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
...
public class ConditionObject implements Condition, java.io.Serializable {
//First node of condition queue.
private transient Node firstWaiter;
//Last node of condition queue.
private transient Node lastWaiter;
...
//Moves the longest-waiting thread, if one exists,
//from the wait queue for this condition to the wait queue for the owning lock.
public final void signal() {
//通过isHeldExclusively()方法检查当前线程是否获取了锁
if (!isHeldExclusively()) {
throw new IllegalMonitorStateException();
}
Node first = firstWaiter;
if (first != null) {
doSignal(first);
}
}
//Removes and transfers nodes until hit non-cancelled one or null.
//Split out from signal in part to encourage compilers to inline the case of no waiters.
private void doSignal(Node first) {
do {
//firstWaiter后移
if ((firstWaiter = first.nextWaiter) == null) {
lastWaiter = null;
}
//firstWaiter出队
first.nextWaiter = null;
} while (!transferForSignal(first) && (first = firstWaiter) != null);
}
//Transfers a node from a condition queue onto sync queue.
//Returns true if successful.
final boolean transferForSignal(Node node) {
//在addConditionWaiter()方法时,node就被封装为CONDITION类型
//如果CAS失败,说明当前结点已被修改为CANCELED,此时需要继续查找Condition队列的下一个结点
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
return false;
}
//将node结点转移到等待队列中,返回等待队列的尾结点
Node p = enq(node);
int ws = p.waitStatus;
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) {
//唤醒node结点
LockSupport.unpark(node.thread);
}
return true;
}
//Implements interruptible condition wait.
//If current thread is interrupted, throw InterruptedException.
public final void await() throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
//1.执行ConditionObject的addConditionWaiter()方法,将当前线程封装成Node结点并加入Condition队列
Node node = addConditionWaiter();
//2.调用AQS的fullyRelease()方法释放锁
int savedState = fullyRelease(node);
int interruptMode = 0;
//一开始node结点并不在等待队列中,所以isOnSyncQueue()方法返回false,进行阻塞
//后来其他线程调用signal()方法,该node结点就会被唤醒,然后发现该node结点已经在等待队列中,于是isOnSyncQueue()方法返回true
while (!isOnSyncQueue(node)) {
//3.阻塞当前线程
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) {
break;
}
}
//4.当前线程被signal()方法唤醒后,执行AQS的acquireQueued()方法尝试获取锁
if (acquireQueued(node, savedState) && interruptMode != THROW_IE) {
interruptMode = REINTERRUPT;
}
if (node.nextWaiter != null) {// clean up if cancelled
unlinkCancelledWaiters();
}
if (interruptMode != 0) {
reportInterruptAfterWait(interruptMode);
}
}
...
}
//Inserts node into queue, initializing if necessary. See picture above.
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node())) {
tail = head;
}
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
...
}