JUC并发—6.AQS源码分析二

大纲

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;                 }             }         }     }     ... }

 

发表评论

评论已关闭。

相关文章