Java多线程系列--“JUC锁”03之 公平锁(一)

来源:互联网 发布:hibernate 数据库方言 编辑:程序博客网 时间:2024/05/16 05:49

概要

本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:
基本概念
ReentrantLock数据结构

参考代码
获取公平锁(基于JDK1.7.0_40)
  一. tryAcquire()
  二. addWaiter()
  三. acquireQueued()
  四. selfInterrupt()
“公平锁”的释放锁的机制在后面一章再做介绍,锁的使用示例请参考“Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock”。

转载请注明出处:http://www.cnblogs.com/skywang12345/p/3496147.html

 

基本概念

本章,我们会讲解“线程获取公平锁”的原理;在讲解之前,需要了解几个基本概念。后面的内容,都是基于这些概念的;这些概念可能比较枯燥,但从这些概念中,能窥见“java锁”的一些架构,这对我们了解锁是有帮助的。
1. AQS -- 指AbstractQueuedSynchronizer类。
    AQS是java中管理“锁”的抽象类,锁的许多公共方法都是在这个类中实现。AQS是独占锁(例如,ReentrantLock)和共享锁(例如,Semaphore)的公共父类。

2. AQS锁的类别 -- 分为“独占锁”和“共享锁”两种。
    (01) 独占锁 -- 锁在一个时间点只能被一个线程锁占有。根据锁的获取机制,它又划分为“公平锁”和“非公平锁”。公平锁,是按照通过CLH等待线程按照先来先得的规则,公平的获取锁;而非公平锁,则当线程要获取锁时,它会无视CLH等待队列而直接获取锁。独占锁的典型实例子是ReentrantLock,此外,ReentrantReadWriteLock.WriteLock也是独占锁。
    (02) 共享锁 -- 能被多个线程同时拥有,能被共享的锁。JUC包中的ReentrantReadWriteLock.ReadLock,CyclicBarrier, CountDownLatch和Semaphore都是共享锁。这些锁的用途和原理,在以后的章节再详细介绍。

3. CLH队列 -- Craig, Landin, and Hagersten lock queue
    CLH队列是AQS中“等待锁”的线程队列。在多线程中,为了保护竞争资源不被多个线程同时操作而起来错误,我们常常需要通过锁来保护这些资源。在独占锁中,竞争资源在一个时间点只能被一个线程锁访问;而其它线程则需要等待。CLH就是管理这些“等待锁”的线程的队列。
    CLH是一个非阻塞的 FIFO 队列。也就是说往里面插入或移除一个节点的时候,在并发条件下不会阻塞,而是通过自旋锁和 CAS 保证节点插入和移除的原子性。

4. CAS函数 -- Compare And Swap 
    CAS函数,是比较并交换函数,它是原子操作函数;即,通过CAS操作的数据都是以原子方式进行的。例如,compareAndSetHead(), compareAndSetTail(), compareAndSetNext()等函数。它们共同的特点是,这些函数所执行的动作是以原子的方式进行的。

本章是围绕“公平锁”如何获取锁而层次展开。“公平锁”涉及到的知识点比较多,但总的来说,不是特别难;如果读者能读懂AQS和ReentrantLock.java这两个类的大致意思,理解锁的原理和机制也就不成问题了。本章只是作者本人对锁的一点点理解,希望这部分知识能帮助您了解“公平锁”的获取过程,认识“锁”的框架。

 

ReentrantLock数据结构

ReentrantLock的UML类图

从图中可以看出:
(01) ReentrantLock实现了Lock接口。
(02) ReentrantLock与sync是组合关系。ReentrantLock中,包含了Sync对象;而且,Sync是AQS的子类;更重要的是,Sync有两个子类FairSync(公平锁)和NonFairSync(非公平锁)。ReentrantLock是一个独占锁,至于它到底是公平锁还是非公平锁,就取决于sync对象是"FairSync的实例"还是"NonFairSync的实例"。

 

参考代码

下面给出Java1.7.0_40版本中,ReentrantLock和AQS的源码,仅供参考!

ReentranLock.java

复制代码
  1 /*  2  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.  3  *  4  *  5  *  6  *  7  *  8  *  9  * 10  * 11  * 12  * 13  * 14  * 15  * 16  * 17  * 18  * 19  * 20  * 21  * 22  * 23  */ 24  25 /* 26  * 27  * 28  * 29  * 30  * 31  * Written by Doug Lea with assistance from members of JCP JSR-166 32  * Expert Group and released to the public domain, as explained at 33  * http://creativecommons.org/publicdomain/zero/1.0/ 34  */ 35  36 package java.util.concurrent.locks; 37 import java.util.*; 38 import java.util.concurrent.*; 39 import java.util.concurrent.atomic.*; 40  41 /** 42  * A reentrant mutual exclusion {@link Lock} with the same basic 43  * behavior and semantics as the implicit monitor lock accessed using 44  * {@code synchronized} methods and statements, but with extended 45  * capabilities. 46  * 47  * <p>A {@code ReentrantLock} is <em>owned</em> by the thread last 48  * successfully locking, but not yet unlocking it. A thread invoking 49  * {@code lock} will return, successfully acquiring the lock, when 50  * the lock is not owned by another thread. The method will return 51  * immediately if the current thread already owns the lock. This can 52  * be checked using methods {@link #isHeldByCurrentThread}, and {@link 53  * #getHoldCount}. 54  * 55  * <p>The constructor for this class accepts an optional 56  * <em>fairness</em> parameter.  When set {@code true}, under 57  * contention, locks favor granting access to the longest-waiting 58  * thread.  Otherwise this lock does not guarantee any particular 59  * access order.  Programs using fair locks accessed by many threads 60  * may display lower overall throughput (i.e., are slower; often much 61  * slower) than those using the default setting, but have smaller 62  * variances in times to obtain locks and guarantee lack of 63  * starvation. Note however, that fairness of locks does not guarantee 64  * fairness of thread scheduling. Thus, one of many threads using a 65  * fair lock may obtain it multiple times in succession while other 66  * active threads are not progressing and not currently holding the 67  * lock. 68  * Also note that the untimed {@link #tryLock() tryLock} method does not 69  * honor the fairness setting. It will succeed if the lock 70  * is available even if other threads are waiting. 71  * 72  * <p>It is recommended practice to <em>always</em> immediately 73  * follow a call to {@code lock} with a {@code try} block, most 74  * typically in a before/after construction such as: 75  * 76  * <pre> 77  * class X { 78  *   private final ReentrantLock lock = new ReentrantLock(); 79  *   // ... 80  * 81  *   public void m() { 82  *     lock.lock();  // block until condition holds 83  *     try { 84  *       // ... method body 85  *     } finally { 86  *       lock.unlock() 87  *     } 88  *   } 89  * } 90  * </pre> 91  * 92  * <p>In addition to implementing the {@link Lock} interface, this 93  * class defines methods {@code isLocked} and 94  * {@code getLockQueueLength}, as well as some associated 95  * {@code protected} access methods that may be useful for 96  * instrumentation and monitoring. 97  * 98  * <p>Serialization of this class behaves in the same way as built-in 99  * locks: a deserialized lock is in the unlocked state, regardless of100  * its state when serialized.101  *102  * <p>This lock supports a maximum of 2147483647 recursive locks by103  * the same thread. Attempts to exceed this limit result in104  * {@link Error} throws from locking methods.105  *106  * @since 1.5107  * @author Doug Lea108  */109 public class ReentrantLock implements Lock, java.io.Serializable {110     private static final long serialVersionUID = 7373984872572414699L;111     /** Synchronizer providing all implementation mechanics */112     private final Sync sync;113 114     /**115      * Base of synchronization control for this lock. Subclassed116      * into fair and nonfair versions below. Uses AQS state to117      * represent the number of holds on the lock.118      */119     abstract static class Sync extends AbstractQueuedSynchronizer {120         private static final long serialVersionUID = -5179523762034025860L;121 122         /**123          * Performs {@link Lock#lock}. The main reason for subclassing124          * is to allow fast path for nonfair version.125          */126         abstract void lock();127 128         /**129          * Performs non-fair tryLock.  tryAcquire is130          * implemented in subclasses, but both need nonfair131          * try for trylock method.132          */133         final boolean nonfairTryAcquire(int acquires) {134             final Thread current = Thread.currentThread();135             int c = getState();136             if (c == 0) {137                 if (compareAndSetState(0, acquires)) {138                     setExclusiveOwnerThread(current);139                     return true;140                 }141             }142             else if (current == getExclusiveOwnerThread()) {143                 int nextc = c + acquires;144                 if (nextc < 0) // overflow145                     throw new Error("Maximum lock count exceeded");146                 setState(nextc);147                 return true;148             }149             return false;150         }151 152         protected final boolean tryRelease(int releases) {153             int c = getState() - releases;154             if (Thread.currentThread() != getExclusiveOwnerThread())155                 throw new IllegalMonitorStateException();156             boolean free = false;157             if (c == 0) {158                 free = true;159                 setExclusiveOwnerThread(null);160             }161             setState(c);162             return free;163         }164 165         protected final boolean isHeldExclusively() {166             // While we must in general read state before owner,167             // we don't need to do so to check if current thread is owner168             return getExclusiveOwnerThread() == Thread.currentThread();169         }170 171         final ConditionObject newCondition() {172             return new ConditionObject();173         }174 175         // Methods relayed from outer class176 177         final Thread getOwner() {178             return getState() == 0 ? null : getExclusiveOwnerThread();179         }180 181         final int getHoldCount() {182             return isHeldExclusively() ? getState() : 0;183         }184 185         final boolean isLocked() {186             return getState() != 0;187         }188 189         /**190          * Reconstitutes this lock instance from a stream.191          * @param s the stream192          */193         private void readObject(java.io.ObjectInputStream s)194             throws java.io.IOException, ClassNotFoundException {195             s.defaultReadObject();196             setState(0); // reset to unlocked state197         }198     }199 200     /**201      * Sync object for non-fair locks202      */203     static final class NonfairSync extends Sync {204         private static final long serialVersionUID = 7316153563782823691L;205 206         /**207          * Performs lock.  Try immediate barge, backing up to normal208          * acquire on failure.209          */210         final void lock() {211             if (compareAndSetState(0, 1))212                 setExclusiveOwnerThread(Thread.currentThread());213             else214                 acquire(1);215         }216 217         protected final boolean tryAcquire(int acquires) {218             return nonfairTryAcquire(acquires);219         }220     }221 222     /**223      * Sync object for fair locks224      */225     static final class FairSync extends Sync {226         private static final long serialVersionUID = -3000897897090466540L;227 228         final void lock() {229             acquire(1);230         }231 232         /**233          * Fair version of tryAcquire.  Don't grant access unless234          * recursive call or no waiters or is first.235          */236         protected final boolean tryAcquire(int acquires) {237             final Thread current = Thread.currentThread();238             int c = getState();239             if (c == 0) {240                 if (!hasQueuedPredecessors() &&241                     compareAndSetState(0, acquires)) {242                     setExclusiveOwnerThread(current);243                     return true;244                 }245             }246             else if (current == getExclusiveOwnerThread()) {247                 int nextc = c + acquires;248                 if (nextc < 0)249                     throw new Error("Maximum lock count exceeded");250                 setState(nextc);251                 return true;252             }253             return false;254         }255     }256 257     /**258      * Creates an instance of {@code ReentrantLock}.259      * This is equivalent to using {@code ReentrantLock(false)}.260      */261     public ReentrantLock() {262         sync = new NonfairSync();263     }264 265     /**266      * Creates an instance of {@code ReentrantLock} with the267      * given fairness policy.268      *269      * @param fair {@code true} if this lock should use a fair ordering policy270      */271     public ReentrantLock(boolean fair) {272         sync = fair ? new FairSync() : new NonfairSync();273     }274 275     /**276      * Acquires the lock.277      *278      * <p>Acquires the lock if it is not held by another thread and returns279      * immediately, setting the lock hold count to one.280      *281      * <p>If the current thread already holds the lock then the hold282      * count is incremented by one and the method returns immediately.283      *284      * <p>If the lock is held by another thread then the285      * current thread becomes disabled for thread scheduling286      * purposes and lies dormant until the lock has been acquired,287      * at which time the lock hold count is set to one.288      */289     public void lock() {290         sync.lock();291     }292 293     /**294      * Acquires the lock unless the current thread is295      * {@linkplain Thread#interrupt interrupted}.296      *297      * <p>Acquires the lock if it is not held by another thread and returns298      * immediately, setting the lock hold count to one.299      *300      * <p>If the current thread already holds this lock then the hold count301      * is incremented by one and the method returns immediately.302      *303      * <p>If the lock is held by another thread then the304      * current thread becomes disabled for thread scheduling305      * purposes and lies dormant until one of two things happens:306      *307      * <ul>308      *309      * <li>The lock is acquired by the current thread; or310      *311      * <li>Some other thread {@linkplain Thread#interrupt interrupts} the312      * current thread.313      *314      * </ul>315      *316      * <p>If the lock is acquired by the current thread then the lock hold317      * count is set to one.318      *319      * <p>If the current thread:320      *321      * <ul>322      *323      * <li>has its interrupted status set on entry to this method; or324      *325      * <li>is {@linkplain Thread#interrupt interrupted} while acquiring326      * the lock,327      *328      * </ul>329      *330      * then {@link InterruptedException} is thrown and the current thread's331      * interrupted status is cleared.332      *333      * <p>In this implementation, as this method is an explicit334      * interruption point, preference is given to responding to the335      * interrupt over normal or reentrant acquisition of the lock.336      *337      * @throws InterruptedException if the current thread is interrupted338      */339     public void lockInterruptibly() throws InterruptedException {340         sync.acquireInterruptibly(1);341     }342 343     /**344      * Acquires the lock only if it is not held by another thread at the time345      * of invocation.346      *347      * <p>Acquires the lock if it is not held by another thread and348      * returns immediately with the value {@code true}, setting the349      * lock hold count to one. Even when this lock has been set to use a350      * fair ordering policy, a call to {@code tryLock()} <em>will</em>351      * immediately acquire the lock if it is available, whether or not352      * other threads are currently waiting for the lock.353      * This &quot;barging&quot; behavior can be useful in certain354      * circumstances, even though it breaks fairness. If you want to honor355      * the fairness setting for this lock, then use356      * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }357      * which is almost equivalent (it also detects interruption).358      *359      * <p> If the current thread already holds this lock then the hold360      * count is incremented by one and the method returns {@code true}.361      *362      * <p>If the lock is held by another thread then this method will return363      * immediately with the value {@code false}.364      *365      * @return {@code true} if the lock was free and was acquired by the366      *         current thread, or the lock was already held by the current367      *         thread; and {@code false} otherwise368      */369     public boolean tryLock() {370         return sync.nonfairTryAcquire(1);371     }372 373     /**374      * Acquires the lock if it is not held by another thread within the given375      * waiting time and the current thread has not been376      * {@linkplain Thread#interrupt interrupted}.377      *378      * <p>Acquires the lock if it is not held by another thread and returns379      * immediately with the value {@code true}, setting the lock hold count380      * to one. If this lock has been set to use a fair ordering policy then381      * an available lock <em>will not</em> be acquired if any other threads382      * are waiting for the lock. This is in contrast to the {@link #tryLock()}383      * method. If you want a timed {@code tryLock} that does permit barging on384      * a fair lock then combine the timed and un-timed forms together:385      *386      * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }387      * </pre>388      *389      * <p>If the current thread390      * already holds this lock then the hold count is incremented by one and391      * the method returns {@code true}.392      *393      * <p>If the lock is held by another thread then the394      * current thread becomes disabled for thread scheduling395      * purposes and lies dormant until one of three things happens:396      *397      * <ul>398      *399      * <li>The lock is acquired by the current thread; or400      *401      * <li>Some other thread {@linkplain Thread#interrupt interrupts}402      * the current thread; or403      *404      * <li>The specified waiting time elapses405      *406      * </ul>407      *408      * <p>If the lock is acquired then the value {@code true} is returned and409      * the lock hold count is set to one.410      *411      * <p>If the current thread:412      *413      * <ul>414      *415      * <li>has its interrupted status set on entry to this method; or416      *417      * <li>is {@linkplain Thread#interrupt interrupted} while418      * acquiring the lock,419      *420      * </ul>421      * then {@link InterruptedException} is thrown and the current thread's422      * interrupted status is cleared.423      *424      * <p>If the specified waiting time elapses then the value {@code false}425      * is returned.  If the time is less than or equal to zero, the method426      * will not wait at all.427      *428      * <p>In this implementation, as this method is an explicit429      * interruption point, preference is given to responding to the430      * interrupt over normal or reentrant acquisition of the lock, and431      * over reporting the elapse of the waiting time.432      *433      * @param timeout the time to wait for the lock434      * @param unit the time unit of the timeout argument435      * @return {@code true} if the lock was free and was acquired by the436      *         current thread, or the lock was already held by the current437      *         thread; and {@code false} if the waiting time elapsed before438      *         the lock could be acquired439      * @throws InterruptedException if the current thread is interrupted440      * @throws NullPointerException if the time unit is null441      *442      */443     public boolean tryLock(long timeout, TimeUnit unit)444             throws InterruptedException {445         return sync.tryAcquireNanos(1, unit.toNanos(timeout));446     }447 448     /**449      * Attempts to release this lock.450      *451      * <p>If the current thread is the holder of this lock then the hold452      * count is decremented.  If the hold count is now zero then the lock453      * is released.  If the current thread is not the holder of this454      * lock then {@link IllegalMonitorStateException} is thrown.455      *456      * @throws IllegalMonitorStateException if the current thread does not457      *         hold this lock458      */459     public void unlock() {460         sync.release(1);461     }462 463     /**464      * Returns a {@link Condition} instance for use with this465      * {@link Lock} instance.466      *467      * <p>The returned {@link Condition} instance supports the same468      * usages as do the {@link Object} monitor methods ({@link469      * Object#wait() wait}, {@link Object#notify notify}, and {@link470      * Object#notifyAll notifyAll}) when used with the built-in471      * monitor lock.472      *473      * <ul>474      *475      * <li>If this lock is not held when any of the {@link Condition}476      * {@linkplain Condition#await() waiting} or {@linkplain477      * Condition#signal signalling} methods are called, then an {@link478      * IllegalMonitorStateException} is thrown.479      *480      * <li>When the condition {@linkplain Condition#await() waiting}481      * methods are called the lock is released and, before they482      * return, the lock is reacquired and the lock hold count restored483      * to what it was when the method was called.484      *485      * <li>If a thread is {@linkplain Thread#interrupt interrupted}486      * while waiting then the wait will terminate, an {@link487      * InterruptedException} will be thrown, and the thread's488      * interrupted status will be cleared.489      *490      * <li> Waiting threads are signalled in FIFO order.491      *492      * <li>The ordering of lock reacquisition for threads returning493      * from waiting methods is the same as for threads initially494      * acquiring the lock, which is in the default case not specified,495      * but for <em>fair</em> locks favors those threads that have been496      * waiting the longest.497      *498      * </ul>499      *500      * @return the Condition object501      */502     public Condition newCondition() {503         return sync.newCondition();504     }505 506     /**507      * Queries the number of holds on this lock by the current thread.508      *509      * <p>A thread has a hold on a lock for each lock action that is not510      * matched by an unlock action.511      *512      * <p>The hold count information is typically only used for testing and513      * debugging purposes. For example, if a certain section of code should514      * not be entered with the lock already held then we can assert that515      * fact:516      *517      * <pre>518      * class X {519      *   ReentrantLock lock = new ReentrantLock();520      *   // ...521      *   public void m() {522      *     assert lock.getHoldCount() == 0;523      *     lock.lock();524      *     try {525      *       // ... method body526      *     } finally {527      *       lock.unlock();528      *     }529      *   }530      * }531      * </pre>532      *533      * @return the number of holds on this lock by the current thread,534      *         or zero if this lock is not held by the current thread535      */536     public int getHoldCount() {537         return sync.getHoldCount();538     }539 540     /**541      * Queries if this lock is held by the current thread.542      *543      * <p>Analogous to the {@link Thread#holdsLock} method for built-in544      * monitor locks, this method is typically used for debugging and545      * testing. For example, a method that should only be called while546      * a lock is held can assert that this is the case:547      *548      * <pre>549      * class X {550      *   ReentrantLock lock = new ReentrantLock();551      *   // ...552      *553      *   public void m() {554      *       assert lock.isHeldByCurrentThread();555      *       // ... method body556      *   }557      * }558      * </pre>559      *560      * <p>It can also be used to ensure that a reentrant lock is used561      * in a non-reentrant manner, for example:562      *563      * <pre>564      * class X {565      *   ReentrantLock lock = new ReentrantLock();566      *   // ...567      *568      *   public void m() {569      *       assert !lock.isHeldByCurrentThread();570      *       lock.lock();571      *       try {572      *           // ... method body573      *       } finally {574      *           lock.unlock();575      *       }576      *   }577      * }578      * </pre>579      *580      * @return {@code true} if current thread holds this lock and581      *         {@code false} otherwise582      */583     public boolean isHeldByCurrentThread() {584         return sync.isHeldExclusively();585     }586 587     /**588      * Queries if this lock is held by any thread. This method is589      * designed for use in monitoring of the system state,590      * not for synchronization control.591      *592      * @return {@code true} if any thread holds this lock and593      *         {@code false} otherwise594      */595     public boolean isLocked() {596         return sync.isLocked();597     }598 599     /**600      * Returns {@code true} if this lock has fairness set true.601      *602      * @return {@code true} if this lock has fairness set true603      */604     public final boolean isFair() {605         return sync instanceof FairSync;606     }607 608     /**609      * Returns the thread that currently owns this lock, or610      * {@code null} if not owned. When this method is called by a611      * thread that is not the owner, the return value reflects a612      * best-effort approximation of current lock status. For example,613      * the owner may be momentarily {@code null} even if there are614      * threads trying to acquire the lock but have not yet done so.615      * This method is designed to facilitate construction of616      * subclasses that provide more extensive lock monitoring617      * facilities.618      *619      * @return the owner, or {@code null} if not owned620      */621     protected Thread getOwner() {622         return sync.getOwner();623     }624 625     /**626      * Queries whether any threads are waiting to acquire this lock. Note that627      * because cancellations may occur at any time, a {@code true}628      * return does not guarantee that any other thread will ever629      * acquire this lock.  This method is designed primarily for use in630      * monitoring of the system state.631      *632      * @return {@code true} if there may be other threads waiting to633      *         acquire the lock634      */635     public final boolean hasQueuedThreads() {636         return sync.hasQueuedThreads();637     }638 639 640     /**641      * Queries whether the given thread is waiting to acquire this642      * lock. Note that because cancellations may occur at any time, a643      * {@code true} return does not guarantee that this thread644      * will ever acquire this lock.  This method is designed primarily for use645      * in monitoring of the system state.646      *647      * @param thread the thread648      * @return {@code true} if the given thread is queued waiting for this lock649      * @throws NullPointerException if the thread is null650      */651     public final boolean hasQueuedThread(Thread thread) {652         return sync.isQueued(thread);653     }654 655 656     /**657      * Returns an estimate of the number of threads waiting to658      * acquire this lock.  The value is only an estimate because the number of659      * threads may change dynamically while this method traverses660      * internal data structures.  This method is designed for use in661      * monitoring of the system state, not for synchronization662      * control.663      *664      * @return the estimated number of threads waiting for this lock665      */666     public final int getQueueLength() {667         return sync.getQueueLength();668     }669 670     /**671      * Returns a collection containing threads that may be waiting to672      * acquire this lock.  Because the actual set of threads may change673      * dynamically while constructing this result, the returned674      * collection is only a best-effort estimate.  The elements of the675      * returned collection are in no particular order.  This method is676      * designed to facilitate construction of subclasses that provide677      * more extensive monitoring facilities.678      *679      * @return the collection of threads680      */681     protected Collection<Thread> getQueuedThreads() {682         return sync.getQueuedThreads();683     }684 685     /**686      * Queries whether any threads are waiting on the given condition687      * associated with this lock. Note that because timeouts and688      * interrupts may occur at any time, a {@code true} return does689      * not guarantee that a future {@code signal} will awaken any690      * threads.  This method is designed primarily for use in691      * monitoring of the system state.692      *693      * @param condition the condition694      * @return {@code true} if there are any waiting threads695      * @throws IllegalMonitorStateException if this lock is not held696      * @throws IllegalArgumentException if the given condition is697      *         not associated with this lock698      * @throws NullPointerException if the condition is null699      */700     public boolean hasWaiters(Condition condition) {701         if (condition == null)702             throw new NullPointerException();703         if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))704             throw new IllegalArgumentException("not owner");705         return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);706     }707 708     /**709      * Returns an estimate of the number of threads waiting on the710      * given condition associated with this lock. Note that because711      * timeouts and interrupts may occur at any time, the estimate712      * serves only as an upper bound on the actual number of waiters.713      * This method is designed for use in monitoring of the system714      * state, not for synchronization control.715      *716      * @param condition the condition717      * @return the estimated number of waiting threads718      * @throws IllegalMonitorStateException if this lock is not held719      * @throws IllegalArgumentException if the given condition is720      *         not associated with this lock721      * @throws NullPointerException if the condition is null722      */723     public int getWaitQueueLength(Condition condition) {724         if (condition == null)725             throw new NullPointerException();726         if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))727             throw new IllegalArgumentException("not owner");728         return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);729     }730 731     /**732      * Returns a collection containing those threads that may be733      * waiting on the given condition associated with this lock.734      * Because the actual set of threads may change dynamically while735      * constructing this result, the returned collection is only a736      * best-effort estimate. The elements of the returned collection737      * are in no particular order.  This method is designed to738      * facilitate construction of subclasses that provide more739      * extensive condition monitoring facilities.740      *741      * @param condition the condition742      * @return the collection of threads743      * @throws IllegalMonitorStateException if this lock is not held744      * @throws IllegalArgumentException if the given condition is745      *         not associated with this lock746      * @throws NullPointerException if the condition is null747      */748     protected Collection<Thread> getWaitingThreads(Condition condition) {749         if (condition == null)750             throw new NullPointerException();751         if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))752             throw new IllegalArgumentException("not owner");753         return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);754     }755 756     /**757      * Returns a string identifying this lock, as well as its lock state.758      * The state, in brackets, includes either the String {@code "Unlocked"}759      * or the String {@code "Locked by"} followed by the760      * {@linkplain Thread#getName name} of the owning thread.761      *762      * @return a string identifying this lock, as well as its lock state763      */764     public String toString() {765         Thread o = sync.getOwner();766         return super.toString() + ((o == null) ?767                                    "[Unlocked]" :768                                    "[Locked by thread " + o.getName() + "]");769     }770 }
复制代码

 

AQS(AbstractQueuedSynchronizer.java)

复制代码
   1 /*   2  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.   3  *   4  *   5  *   6  *   7  *   8  *   9  *  10  *  11  *  12  *  13  *  14  *  15  *  16  *  17  *  18  *  19  *  20  *  21  *  22  *  23  */  24   25 /*  26  *  27  *  28  *  29  *  30  *  31  * Written by Doug Lea with assistance from members of JCP JSR-166  32  * Expert Group and released to the public domain, as explained at  33  * http://creativecommons.org/publicdomain/zero/1.0/  34  */  35   36 package java.util.concurrent.locks;  37 import java.util.*;  38 import java.util.concurrent.*;  39 import java.util.concurrent.atomic.*;  40 import sun.misc.Unsafe;  41   42 /**  43  * Provides a framework for implementing blocking locks and related  44  * synchronizers (semaphores, events, etc) that rely on  45  * first-in-first-out (FIFO) wait queues.  This class is designed to  46  * be a useful basis for most kinds of synchronizers that rely on a  47  * single atomic <tt>int</tt> value to represent state. Subclasses  48  * must define the protected methods that change this state, and which  49  * define what that state means in terms of this object being acquired  50  * or released.  Given these, the other methods in this class carry  51  * out all queuing and blocking mechanics. Subclasses can maintain  52  * other state fields, but only the atomically updated <tt>int</tt>  53  * value manipulated using methods {@link #getState}, {@link  54  * #setState} and {@link #compareAndSetState} is tracked with respect  55  * to synchronization.  56  *  57  * <p>Subclasses should be defined as non-public internal helper  58  * classes that are used to implement the synchronization properties  59  * of their enclosing class.  Class  60  * <tt>AbstractQueuedSynchronizer</tt> does not implement any  61  * synchronization interface.  Instead it defines methods such as  62  * {@link #acquireInterruptibly} that can be invoked as  63  * appropriate by concrete locks and related synchronizers to  64  * implement their public methods.  65  *  66  * <p>This class supports either or both a default <em>exclusive</em>  67  * mode and a <em>shared</em> mode. When acquired in exclusive mode,  68  * attempted acquires by other threads cannot succeed. Shared mode  69  * acquires by multiple threads may (but need not) succeed. This class  70  * does not &quot;understand&quot; these differences except in the  71  * mechanical sense that when a shared mode acquire succeeds, the next  72  * waiting thread (if one exists) must also determine whether it can  73  * acquire as well. Threads waiting in the different modes share the  74  * same FIFO queue. Usually, implementation subclasses support only  75  * one of these modes, but both can come into play for example in a  76  * {@link ReadWriteLock}. Subclasses that support only exclusive or  77  * only shared modes need not define the methods supporting the unused mode.  78  *  79  * <p>This class defines a nested {@link ConditionObject} class that  80  * can be used as a {@link Condition} implementation by subclasses  81  * supporting exclusive mode for which method {@link  82  * #isHeldExclusively} reports whether synchronization is exclusively  83  * held with respect to the current thread, method {@link #release}  84  * invoked with the current {@link #getState} value fully releases  85  * this object, and {@link #acquire}, given this saved state value,  86  * eventually restores this object to its previous acquired state.  No  87  * <tt>AbstractQueuedSynchronizer</tt> method otherwise creates such a  88  * condition, so if this constraint cannot be met, do not use it.  The  89  * behavior of {@link ConditionObject} depends of course on the  90  * semantics of its synchronizer implementation.  91  *  92  * <p>This class provides inspection, instrumentation, and monitoring  93  * methods for the internal queue, as well as similar methods for  94  * condition objects. These can be exported as desired into classes  95  * using an <tt>AbstractQueuedSynchronizer</tt> for their  96  * synchronization mechanics.  97  *  98  * <p>Serialization of this class stores only the underlying atomic  99  * integer maintaining state, so deserialized objects have empty 100  * thread queues. Typical subclasses requiring serializability will 101  * define a <tt>readObject</tt> method that restores this to a known 102  * initial state upon deserialization. 103  * 104  * <h3>Usage</h3> 105  * 106  * <p>To use this class as the basis of a synchronizer, redefine the 107  * following methods, as applicable, by inspecting and/or modifying 108  * the synchronization state using {@link #getState}, {@link 109  * #setState} and/or {@link #compareAndSetState}: 110  * 111  * <ul> 112  * <li> {@link #tryAcquire} 113  * <li> {@link #tryRelease} 114  * <li> {@link #tryAcquireShared} 115  * <li> {@link #tryReleaseShared} 116  * <li> {@link #isHeldExclusively} 117  *</ul> 118  * 119  * Each of these methods by default throws {@link 120  * UnsupportedOperationException}.  Implementations of these methods 121  * must be internally thread-safe, and should in general be short and 122  * not block. Defining these methods is the <em>only</em> supported 123  * means of using this class. All other methods are declared 124  * <tt>final</tt> because they cannot be independently varied. 125  * 126  * <p>You may also find the inherited methods from {@link 127  * AbstractOwnableSynchronizer} useful to keep track of the thread 128  * owning an exclusive synchronizer.  You are encouraged to use them 129  * -- this enables monitoring and diagnostic tools to assist users in 130  * determining which threads hold locks. 131  * 132  * <p>Even though this class is based on an internal FIFO queue, it 133  * does not automatically enforce FIFO acquisition policies.  The core 134  * of exclusive synchronization takes the form: 135  * 136  * <pre> 137  * Acquire: 138  *     while (!tryAcquire(arg)) { 139  *        <em>enqueue thread if it is not already queued</em>; 140  *        <em>possibly block current thread</em>; 141  *     } 142  * 143  * Release: 144  *     if (tryRelease(arg)) 145  *        <em>unblock the first queued thread</em>; 146  * </pre> 147  * 148  * (Shared mode is similar but may involve cascading signals.) 149  * 150  * <p><a name="barging">Because checks in acquire are invoked before 151  * enqueuing, a newly acquiring thread may <em>barge</em> ahead of 152  * others that are blocked and queued.  However, you can, if desired, 153  * define <tt>tryAcquire</tt> and/or <tt>tryAcquireShared</tt> to 154  * disable barging by internally invoking one or more of the inspection 155  * methods, thereby providing a <em>fair</em> FIFO acquisition order. 156  * In particular, most fair synchronizers can define <tt>tryAcquire</tt> 157  * to return <tt>false</tt> if {@link #hasQueuedPredecessors} (a method 158  * specifically designed to be used by fair synchronizers) returns 159  * <tt>true</tt>.  Other variations are possible. 160  * 161  * <p>Throughput and scalability are generally highest for the 162  * default barging (also known as <em>greedy</em>, 163  * <em>renouncement</em>, and <em>convoy-avoidance</em>) strategy. 164  * While this is not guaranteed to be fair or starvation-free, earlier 165  * queued threads are allowed to recontend before later queued 166  * threads, and each recontention has an unbiased chance to succeed 167  * against incoming threads.  Also, while acquires do not 168  * &quot;spin&quot; in the usual sense, they may perform multiple 169  * invocations of <tt>tryAcquire</tt> interspersed with other 170  * computations before blocking.  This gives most of the benefits of 171  * spins when exclusive synchronization is only briefly held, without 172  * most of the liabilities when it isn't. If so desired, you can 173  * augment this by preceding calls to acquire methods with 174  * "fast-path" checks, possibly prechecking {@link #hasContended} 175  * and/or {@link #hasQueuedThreads} to only do so if the synchronizer 176  * is likely not to be contended. 177  * 178  * <p>This class provides an efficient and scalable basis for 179  * synchronization in part by specializing its range of use to 180  * synchronizers that can rely on <tt>int</tt> state, acquire, and 181  * release parameters, and an internal FIFO wait queue. When this does 182  * not suffice, you can build synchronizers from a lower level using 183  * {@link java.util.concurrent.atomic atomic} classes, your own custom 184  * {@link java.util.Queue} classes, and {@link LockSupport} blocking 185  * support. 186  * 187  * <h3>Usage Examples</h3> 188  * 189  * <p>Here is a non-reentrant mutual exclusion lock class that uses 190  * the value zero to represent the unlocked state, and one to 191  * represent the locked state. While a non-reentrant lock 192  * does not strictly require recording of the current owner 193  * thread, this class does so anyway to make usage easier to monitor. 194  * It also supports conditions and exposes 195  * one of the instrumentation methods: 196  * 197  * <pre> 198  * class Mutex implements Lock, java.io.Serializable { 199  * 200  *   // Our internal helper class 201  *   private static class Sync extends AbstractQueuedSynchronizer { 202  *     // Report whether in locked state 203  *     protected boolean isHeldExclusively() { 204  *       return getState() == 1; 205  *     } 206  * 207  *     // Acquire the lock if state is zero 208  *     public boolean tryAcquire(int acquires) { 209  *       assert acquires == 1; // Otherwise unused 210  *       if (compareAndSetState(0, 1)) { 211  *         setExclusiveOwnerThread(Thread.currentThread()); 212  *         return true; 213  *       } 214  *       return false; 215  *     } 216  * 217  *     // Release the lock by setting state to zero 218  *     protected boolean tryRelease(int releases) { 219  *       assert releases == 1; // Otherwise unused 220  *       if (getState() == 0) throw new IllegalMonitorStateException(); 221  *       setExclusiveOwnerThread(null); 222  *       setState(0); 223  *       return true; 224  *     } 225  * 226  *     // Provide a Condition 227  *     Condition newCondition() { return new ConditionObject(); } 228  * 229  *     // Deserialize properly 230  *     private void readObject(ObjectInputStream s) 231  *         throws IOException, ClassNotFoundException { 232  *       s.defaultReadObject(); 233  *       setState(0); // reset to unlocked state 234  *     } 235  *   } 236  * 237  *   // The sync object does all the hard work. We just forward to it. 238  *   private final Sync sync = new Sync(); 239  * 240  *   public void lock()                { sync.acquire(1); } 241  *   public boolean tryLock()          { return sync.tryAcquire(1); } 242  *   public void unlock()              { sync.release(1); } 243  *   public Condition newCondition()   { return sync.newCondition(); } 244  *   public boolean isLocked()         { return sync.isHeldExclusively(); } 245  *   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } 246  *   public void lockInterruptibly() throws InterruptedException { 247  *     sync.acquireInterruptibly(1); 248  *   } 249  *   public boolean tryLock(long timeout, TimeUnit unit) 250  *       throws InterruptedException { 251  *     return sync.tryAcquireNanos(1, unit.toNanos(timeout)); 252  *   } 253  * } 254  * </pre> 255  * 256  * <p>Here is a latch class that is like a {@link CountDownLatch} 257  * except that it only requires a single <tt>signal</tt> to 258  * fire. Because a latch is non-exclusive, it uses the <tt>shared</tt> 259  * acquire and release methods. 260  * 261  * <pre> 262  * class BooleanLatch { 263  * 264  *   private static class Sync extends AbstractQueuedSynchronizer { 265  *     boolean isSignalled() { return getState() != 0; } 266  * 267  *     protected int tryAcquireShared(int ignore) { 268  *       return isSignalled() ? 1 : -1; 269  *     } 270  * 271  *     protected boolean tryReleaseShared(int ignore) { 272  *       setState(1); 273  *       return true; 274  *     } 275  *   } 276  * 277  *   private final Sync sync = new Sync(); 278  *   public boolean isSignalled() { return sync.isSignalled(); } 279  *   public void signal()         { sync.releaseShared(1); } 280  *   public void await() throws InterruptedException { 281  *     sync.acquireSharedInterruptibly(1); 282  *   } 283  * } 284  * </pre> 285  * 286  * @since 1.5 287  * @author Doug Lea 288  */ 289 public abstract class AbstractQueuedSynchronizer 290     extends AbstractOwnableSynchronizer 291     implements java.io.Serializable { 292  293     private static final long serialVersionUID = 7373984972572414691L; 294  295     /** 296      * Creates a new <tt>AbstractQueuedSynchronizer</tt> instance 297      * with initial synchronization state of zero. 298      */ 299     protected AbstractQueuedSynchronizer() { } 300  301     /** 302      * Wait queue node class. 303      * 304      * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and 305      * Hagersten) lock queue. CLH locks are normally used for 306      * spinlocks.  We instead use them for blocking synchronizers, but 307      * use the same basic tactic of holding some of the control 308      * information about a thread in the predecessor of its node.  A 309      * "status" field in each node keeps track of whether a thread 310      * should block.  A node is signalled when its predecessor 311      * releases.  Each node of the queue otherwise serves as a 312      * specific-notification-style monitor holding a single waiting 313      * thread. The status field does NOT control whether threads are 314      * granted locks etc though.  A thread may try to acquire if it is 315      * first in the queue. But being first does not guarantee success; 316      * it only gives the right to contend.  So the currently released 317      * contender thread may need to rewait. 318      * 319      * <p>To enqueue into a CLH lock, you atomically splice it in as new 320      * tail. To dequeue, you just set the head field. 321      * <pre> 322      *      +------+  prev +-----+       +-----+ 323      * head |      | <---- |     | <---- |     |  tail 324      *      +------+       +-----+       +-----+ 325      * </pre> 326      * 327      * <p>Insertion into a CLH queue requires only a single atomic 328      * operation on "tail", so there is a simple atomic point of 329      * demarcation from unqueued to queued. Similarly, dequeing 330      * involves only updating the "head". However, it takes a bit 331      * more work for nodes to determine who their successors are, 332      * in part to deal with possible cancellation due to timeouts 333      * and interrupts. 334      * 335      * <p>The "prev" links (not used in original CLH locks), are mainly 336      * needed to handle cancellation. If a node is cancelled, its 337      * successor is (normally) relinked to a non-cancelled 338      * predecessor. For explanation of similar mechanics in the case 339      * of spin locks, see the papers by Scott and Scherer at 340      * http://www.cs.rochester.edu/u/scott/synchronization/ 341      * 342      * <p>We also use "next" links to implement blocking mechanics. 343      * The thread id for each node is kept in its own node, so a 344      * predecessor signals the next node to wake up by traversing 345      * next link to determine which thread it is.  Determination of 346      * successor must avoid races with newly queued nodes to set 347      * the "next" fields of their predecessors.  This is solved 348      * when necessary by checking backwards from the atomically 349      * updated "tail" when a node's successor appears to be null. 350      * (Or, said differently, the next-links are an optimization 351      * so that we don't usually need a backward scan.) 352      * 353      * <p>Cancellation introduces some conservatism to the basic 354      * algorithms.  Since we must poll for cancellation of other 355      * nodes, we can miss noticing whether a cancelled node is 356      * ahead or behind us. This is dealt with by always unparking 357      * successors upon cancellation, allowing them to stabilize on 358      * a new predecessor, unless we can identify an uncancelled 359      * predecessor who will carry this responsibility. 360      * 361      * <p>CLH queues need a dummy header node to get started. But 362      * we don't create them on construction, because it would be wasted 363      * effort if there is never contention. Instead, the node 364      * is constructed and head and tail pointers are set upon first 365      * contention. 366      * 367      * <p>Threads waiting on Conditions use the same nodes, but 368      * use an additional link. Conditions only need to link nodes 369      * in simple (non-concurrent) linked queues because they are 370      * only accessed when exclusively held.  Upon await, a node is 371      * inserted into a condition queue.  Upon signal, the node is 372      * transferred to the main queue.  A special value of status 373      * field is used to mark which queue a node is on. 374      * 375      * <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill 376      * Scherer and Michael Scott, along with members of JSR-166 377      * expert group, for helpful ideas, discussions, and critiques 378      * on the design of this class. 379      */ 380     static final class Node { 381         /** Marker to indicate a node is waiting in shared mode */ 382         static final Node SHARED = new Node(); 383         /** Marker to indicate a node is waiting in exclusive mode */ 384         static final Node EXCLUSIVE = null; 385  386         /** waitStatus value to indicate thread has cancelled */ 387         static final int CANCELLED =  1; 388         /** waitStatus value to indicate successor's thread needs unparking */ 389         static final int SIGNAL    = -1; 390         /** waitStatus value to indicate thread is waiting on condition */ 391         static final int CONDITION = -2; 392         /** 393          * waitStatus value to indicate the next acquireShared should 394          * unconditionally propagate 395          */ 396         static final int PROPAGATE = -3; 397  398         /** 399          * Status field, taking on only the values: 400          *   SIGNAL:     The successor of this node is (or will soon be) 401          *               blocked (via park), so the current node must 402          *               unpark its successor when it releases or 403          *               cancels. To avoid races, acquire methods must 404          *               first indicate they need a signal, 405          *               then retry the atomic acquire, and then, 406          *               on failure, block. 407          *   CANCELLED:  This node is cancelled due to timeout or interrupt. 408          *               Nodes never leave this state. In particular, 409          *               a thread with cancelled node never again blocks. 410          *   CONDITION:  This node is currently on a condition queue. 411          *               It will not be used as a sync queue node 412          *               until transferred, at which time the status 413          *               will be set to 0. (Use of this value here has 414          *               nothing to do with the other uses of the 415          *               field, but simplifies mechanics.) 416          *   PROPAGATE:  A releaseShared should be propagated to other 417          *               nodes. This is set (for head node only) in 418          *               doReleaseShared to ensure propagation 419          *               continues, even if other operations have 420          *               since intervened. 421          *   0:          None of the above 422          * 423          * The values are arranged numerically to simplify use. 424          * Non-negative values mean that a node doesn't need to 425          * signal. So, most code doesn't need to check for particular 426          * values, just for sign. 427          * 428          * The field is initialized to 0 for normal sync nodes, and 429          * CONDITION for condition nodes.  It is modified using CAS 430          * (or when possible, unconditional volatile writes). 431          */ 432         volatile int waitStatus; 433  434         /** 435          * Link to predecessor node that current node/thread relies on 436          * for checking waitStatus. Assigned during enqueing, and nulled 437          * out (for sake of GC) only upon dequeuing.  Also, upon 438          * cancellation of a predecessor, we short-circuit while 439          * finding a non-cancelled one, which will always exist 440          * because the head node is never cancelled: A node becomes 441          * head only as a result of successful acquire. A 442          * cancelled thread never succeeds in acquiring, and a thread only 443          * cancels itself, not any other node. 444          */ 445         volatile Node prev; 446  447         /** 448          * Link to the successor node that the current node/thread 449          * unparks upon release. Assigned during enqueuing, adjusted 450          * when bypassing cancelled predecessors, and nulled out (for 451          * sake of GC) when dequeued.  The enq operation does not 452          * assign next field of a predecessor until after attachment, 453          * so seeing a null next field does not necessarily mean that 454          * node is at end of queue. However, if a next field appears 455          * to be null, we can scan prev's from the tail to 456          * double-check.  The next field of cancelled nodes is set to 457          * point to the node itself instead of null, to make life 458          * easier for isOnSyncQueue. 459          */ 460         volatile Node next; 461  462         /** 463          * The thread that enqueued this node.  Initialized on 464          * construction and nulled out after use. 465          */ 466         volatile Thread thread; 467  468         /** 469          * Link to next node waiting on condition, or the special 470          * value SHARED.  Because condition queues are accessed only 471          * when holding in exclusive mode, we just need a simple 472          * linked queue to hold nodes while they are waiting on 473          * conditions. They are then transferred to the queue to 474          * re-acquire. And because conditions can only be exclusive, 475          * we save a field by using special value to indicate shared 476          * mode. 477          */ 478         Node nextWaiter; 479  480         /** 481          * Returns true if node is waiting in shared mode 482          */ 483         final boolean isShared() { 484             return nextWaiter == SHARED; 485         } 486  487         /** 488          * Returns previous node, or throws NullPointerException if null. 489          * Use when predecessor cannot be null.  The null check could 490          * be elided, but is present to help the VM. 491          * 492          * @return the predecessor of this node 493          */ 494         final Node predecessor() throws NullPointerException { 495             Node p = prev; 496             if (p == null) 497                 throw new NullPointerException(); 498             else 499                 return p; 500         } 501  502         Node() {    // Used to establish initial head or SHARED marker 503         } 504  505         Node(Thread thread, Node mode) {     // Used by addWaiter 506             this.nextWaiter = mode; 507             this.thread = thread; 508         } 509  510         Node(Thread thread, int waitStatus) { // Used by Condition 511             this.waitStatus = waitStatus; 512             this.thread = thread; 513         } 514     } 515  516     /** 517      * Head of the wait queue, lazily initialized.  Except for 518      * initialization, it is modified only via method setHead.  Note: 519      * If head exists, its waitStatus is guaranteed not to be 520      * CANCELLED. 521      */ 522     private transient volatile Node head; 523  524     /** 525      * Tail of the wait queue, lazily initialized.  Modified only via 526      * method enq to add new wait node. 527      */ 528     private transient volatile Node tail; 529  530     /** 531      * The synchronization state. 532      */ 533     private volatile int state; 534  535     /** 536      * Returns the current value of synchronization state. 537      * This operation has memory semantics of a <tt>volatile</tt> read. 538      * @return current state value 539      */ 540     protected final int getState() { 541         return state; 542     } 543  544     /** 545      * Sets the value of synchronization state. 546      * This operation has memory semantics of a <tt>volatile</tt> write. 547      * @param newState the new state value 548      */ 549     protected final void setState(int newState) { 550         state = newState; 551     } 552  553     /** 554      * Atomically sets synchronization state to the given updated 555      * value if the current state value equals the expected value. 556      * This operation has memory semantics of a <tt>volatile</tt> read 557      * and write. 558      * 559      * @param expect the expected value 560      * @param update the new value 561      * @return true if successful. False return indicates that the actual 562      *         value was not equal to the expected value. 563      */ 564     protected final boolean compareAndSetState(int expect, int update) { 565         // See below for intrinsics setup to support this 566         return unsafe.compareAndSwapInt(this, stateOffset, expect, update); 567     } 568  569     // Queuing utilities 570  571     /** 572      * The number of nanoseconds for which it is faster to spin 573      * rather than to use timed park. A rough estimate suffices 574      * to improve responsiveness with very short timeouts. 575      */ 576     static final long spinForTimeoutThreshold = 1000L; 577  578     /** 579      * Inserts node into queue, initializing if necessary. See picture above. 580      * @param node the node to insert 581      * @return node's predecessor 582      */ 583     private Node enq(final Node node) { 584         for (;;) { 585             Node t = tail; 586             if (t == null) { // Must initialize 587                 if (compareAndSetHead(new Node())) 588                     tail = head; 589             } else { 590                 node.prev = t; 591                 if (compareAndSetTail(t, node)) { 592                     t.next = node; 593                     return t; 594                 } 595             } 596         } 597     } 598  599     /** 600      * Creates and enqueues node for current thread and given mode. 601      * 602      * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared 603      * @return the new node 604      */ 605     private Node addWaiter(Node mode) { 606         Node node = new Node(Thread.currentThread(), mode); 607         // Try the fast path of enq; backup to full enq on failure 608         Node pred = tail; 609         if (pred != null) { 610             node.prev = pred; 611             if (compareAndSetTail(pred, node)) { 612                 pred.next = node; 613                 return node; 614             } 615         } 616         enq(node); 617         return node; 618     } 619  620     /** 621      * Sets head of queue to be node, thus dequeuing. Called only by 622      * acquire methods.  Also nulls out unused fields for sake of GC 623      * and to suppress unnecessary signals and traversals. 624      * 625      * @param node the node 626      */ 627     private void setHead(Node node) { 628         head = node; 629         node.thread = null; 630         node.prev = null; 631     } 632  633     /** 634      * Wakes up node's successor, if one exists. 635      * 636      * @param node the node 637      */ 638     private void unparkSuccessor(Node node) { 639         /* 640          * If status is negative (i.e., possibly needing signal) try 641          * to clear in anticipation of signalling.  It is OK if this 642          * fails or if status is changed by waiting thread. 643          */ 644         int ws = node.waitStatus; 645         if (ws < 0) 646             compareAndSetWaitStatus(node, ws, 0); 647  648         /* 649          * Thread to unpark is held in successor, which is normally 650          * just the next node.  But if cancelled or apparently null, 651          * traverse backwards from tail to find the actual 652          * non-cancelled successor. 653          */ 654         Node s = node.next; 655         if (s == null || s.waitStatus > 0) { 656             s = null; 657             for (Node t = tail; t != null && t != node; t = t.prev) 658                 if (t.waitStatus <= 0) 659                     s = t; 660         } 661         if (s != null) 662             LockSupport.unpark(s.thread); 663     } 664  665     /** 666      * Release action for shared mode -- signal successor and ensure 667      * propagation. (Note: For exclusive mode, release just amounts 668      * to calling unparkSuccessor of head if it needs signal.) 669      */ 670     private void doReleaseShared() { 671         /* 672          * Ensure that a release propagates, even if there are other 673          * in-progress acquires/releases.  This proceeds in the usual 674          * way of trying to unparkSuccessor of head if it needs 675          * signal. But if it does not, status is set to PROPAGATE to 676          * ensure that upon release, propagation continues. 677          * Additionally, we must loop in case a new node is added 678          * while we are doing this. Also, unlike other uses of 679          * unparkSuccessor, we need to know if CAS to reset status 680          * fails, if so rechecking. 681          */ 682         for (;;) { 683             Node h = head; 684             if (h != null && h != tail) { 685                 int ws = h.waitStatus; 686                 if (ws == Node.SIGNAL) { 687                     if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) 688                         continue;            // loop to recheck cases 689                     unparkSuccessor(h); 690                 } 691                 else if (ws == 0 && 692                          !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) 693                     continue;                // loop on failed CAS 694             } 695             if (h == head)                   // loop if head changed 696                 break; 697         } 698     } 699  700     /** 701      * Sets head of queue, and checks if successor may be waiting 702      * in shared mode, if so propagating if either propagate > 0 or 703      * PROPAGATE status was set. 704      * 705      * @param node the node 706      * @param propagate the return value from a tryAcquireShared 707      */ 708     private void setHeadAndPropagate(Node node, int propagate) { 709         Node h = head; // Record old head for check below 710         setHead(node); 711         /* 712          * Try to signal next queued node if: 713          *   Propagation was indicated by caller, 714          *     or was recorded (as h.waitStatus) by a previous operation 715          *     (note: this uses sign-check of waitStatus because 716          *      PROPAGATE status may transition to SIGNAL.) 717          * and 718          *   The next node is waiting in shared mode, 719          *     or we don't know, because it appears null 720          * 721          * The conservatism in both of these checks may cause 722          * unnecessary wake-ups, but only when there are multiple 723          * racing acquires/releases, so most need signals now or soon 724          * anyway. 725          */ 726         if (propagate > 0 || h == null || h.waitStatus < 0) { 727             Node s = node.next; 728             if (s == null || s.isShared()) 729                 doReleaseShared(); 730         } 731     } 732  733     // Utilities for various versions of acquire 734  735     /** 736      * Cancels an ongoing attempt to acquire. 737      * 738      * @param node the node 739      */ 740     private void cancelAcquire(Node node) { 741         // Ignore if node doesn't exist 742         if (node == null) 743             return; 744  745         node.thread = null; 746  747         // Skip cancelled predecessors 748         Node pred = node.prev; 749         while (pred.waitStatus > 0) 750             node.prev = pred = pred.prev; 751  752         // predNext is the apparent node to unsplice. CASes below will 753         // fail if not, in which case, we lost race vs another cancel 754         // or signal, so no further action is necessary. 755         Node predNext = pred.next; 756  757         // Can use unconditional write instead of CAS here. 758         // After this atomic step, other Nodes can skip past us. 759         // Before, we are free of interference from other threads. 760         node.waitStatus = Node.CANCELLED; 761  762         // If we are the tail, remove ourselves. 763         if (node == tail && compareAndSetTail(node, pred)) { 764             compareAndSetNext(pred, predNext, null); 765         } else { 766             // If successor needs signal, try to set pred's next-link 767             // so it will get one. Otherwise wake it up to propagate. 768             int ws; 769             if (pred != head && 770                 ((ws = pred.waitStatus) == Node.SIGNAL || 771                  (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && 772                 pred.thread != null) { 773                 Node next = node.next; 774                 if (next != null && next.waitStatus <= 0) 775                     compareAndSetNext(pred, predNext, next); 776             } else { 777                 unparkSuccessor(node); 778             } 779  780             node.next = node; // help GC 781         } 782     } 783  784     /** 785      * Checks and updates status for a node that failed to acquire. 786      * Returns true if thread should block. This is the main signal 787      * control in all acquire loops.  Requires that pred == node.prev 788      * 789      * @param pred node's predecessor holding status 790      * @param node the node 791      * @return {@code true} if thread should block 792      */ 793     private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { 794         int ws = pred.waitStatus; 795         if (ws == Node.SIGNAL) 796             /* 797              * This node has already set status asking a release 798              * to signal it, so it can safely park. 799              */ 800             return true; 801         if (ws > 0) { 802             /* 803              * Predecessor was cancelled. Skip over predecessors and 804              * indicate retry. 805              */ 806             do { 807                 node.prev = pred = pred.prev; 808             } while (pred.waitStatus > 0); 809             pred.next = node; 810         } else { 811             /* 812              * waitStatus must be 0 or PROPAGATE.  Indicate that we 813              * need a signal, but don't park yet.  Caller will need to 814              * retry to make sure it cannot acquire before parking. 815              */ 816             compareAndSetWaitStatus(pred, ws, Node.SIGNAL); 817         } 818         return false; 819     } 820  821     /** 822      * Convenience method to interrupt current thread. 823      */ 824     private static void selfInterrupt() { 825         Thread.currentThread().interrupt(); 826     } 827  828     /** 829      * Convenience method to park and then check if interrupted 830      * 831      * @return {@code true} if interrupted 832      */ 833     private final boolean parkAndCheckInterrupt() { 834         LockSupport.park(this); 835         return Thread.interrupted(); 836     } 837  838     /* 839      * Various flavors of acquire, varying in exclusive/shared and 840      * control modes.  Each is mostly the same, but annoyingly 841      * different.  Only a little bit of factoring is possible due to 842      * interactions of exception mechanics (including ensuring that we 843      * cancel if tryAcquire throws exception) and other control, at 844      * least not without hurting performance too much. 845      */ 846  847     /** 848      * Acquires in exclusive uninterruptible mode for thread already in 849      * queue. Used by condition wait methods as well as acquire. 850      * 851      * @param node the node 852      * @param arg the acquire argument 853      * @return {@code true} if interrupted while waiting 854      */ 855     final boolean acquireQueued(final Node node, int arg) { 856         boolean failed = true; 857         try { 858             boolean interrupted = false; 859             for (;;) { 860                 final Node p = node.predecessor(); 861                 if (p == head && tryAcquire(arg)) { 862                     setHead(node); 863                     p.next = null; // help GC 864                     failed = false; 865                     return interrupted; 866                 } 867                 if (shouldParkAfterFailedAcquire(p, node) && 868                     parkAndCheckInterrupt()) 869                     interrupted = true; 870             } 871         } finally { 872             if (failed) 873                 cancelAcquire(node); 874         } 875     } 876  877     /** 878      * Acquires in exclusive interruptible mode. 879      * @param arg the acquire argument 880      */ 881     private void doAcquireInterruptibly(int arg) 882         throws InterruptedException { 883         final Node node = addWaiter(Node.EXCLUSIVE); 884         boolean failed = true; 885         try { 886             for (;;) { 887                 final Node p = node.predecessor(); 888                 if (p == head && tryAcquire(arg)) { 889                     setHead(node); 890                     p.next = null; // help GC 891                     failed = false; 892                     return; 893                 } 894                 if (shouldParkAfterFailedAcquire(p, node) && 895                     parkAndCheckInterrupt()) 896                     throw new InterruptedException(); 897             } 898         } finally { 899             if (failed) 900                 cancelAcquire(node); 901         } 902     } 903  904     /** 905      * Acquires in exclusive timed mode. 906      * 907      * @param arg the acquire argument 908      * @param nanosTimeout max wait time 909      * @return {@code true} if acquired 910      */ 911     private boolean doAcquireNanos(int arg, long nanosTimeout) 912         throws InterruptedException { 913         long lastTime = System.nanoTime(); 914         final Node node = addWaiter(Node.EXCLUSIVE); 915         boolean failed = true; 916         try { 917             for (;;) { 918                 final Node p = node.predecessor(); 919                 if (p == head && tryAcquire(arg)) { 920                     setHead(node); 921                     p.next = null; // help GC 922                     failed = false; 923                     return true; 924                 } 925                 if (nanosTimeout <= 0) 926                     return false; 927                 if (shouldParkAfterFailedAcquire(p, node) && 928                     nanosTimeout > spinForTimeoutThreshold) 929                     LockSupport.parkNanos(this, nanosTimeout); 930                 long now = System.nanoTime(); 931                 nanosTimeout -= now - lastTime; 932                 lastTime = now; 933                 if (Thread.interrupted()) 934                     throw new InterruptedException(); 935             } 936         } finally { 937             if (failed) 938                 cancelAcquire(node); 939         } 940     } 941  942     /** 943      * Acquires in shared uninterruptible mode. 944      * @param arg the acquire argument 945      */ 946     private void doAcquireShared(int arg) { 947         final Node node = addWaiter(Node.SHARED); 948         boolean failed = true; 949         try { 950             boolean interrupted = false; 951             for (;;) { 952                 final Node p = node.predecessor(); 953                 if (p == head) { 954                     int r = tryAcquireShared(arg); 955                     if (r >= 0) { 956                         setHeadAndPropagate(node, r); 957                         p.next = null; // help GC 958                         if (interrupted) 959                             selfInterrupt(); 960                         failed = false; 961                         return; 962                     } 963                 } 964                 if (shouldParkAfterFailedAcquire(p, node) && 965                     parkAndCheckInterrupt()) 966                     interrupted = true; 967             } 968         } finally { 969             if (failed) 970                 cancelAcquire(node); 971         } 972     } 973  974     /** 975      * Acquires in shared interruptible mode. 976      * @param arg the acquire argument 977      */ 978     private void doAcquireSharedInterruptibly(int arg) 979         throws InterruptedException { 980         final Node node = addWaiter(Node.SHARED); 981         boolean failed = true; 982         try { 983             for (;;) { 984                 final Node p = node.predecessor(); 985                 if (p == head) { 986                     int r = tryAcquireShared(arg); 987                     if (r >= 0) { 988                         setHeadAndPropagate(node, r); 989                         p.next = null; // help GC 990                         failed = false; 991                         return; 992                     } 993                 } 994                 if (shouldParkAfterFailedAcquire(p, node) && 995                     parkAndCheckInterrupt()) 996                     throw new InterruptedException(); 997             } 998         } finally { 999             if (failed)1000                 cancelAcquire(node);1001         }1002     }1003 1004     /**1005      * Acquires in shared timed mode.1006      *1007      * @param arg the acquire argument1008      * @param nanosTimeout max wait time1009      * @return {@code true} if acquired1010      */1011     private boolean doAcquireSharedNanos(int arg, long nanosTimeout)1012         throws InterruptedException {1013 1014         long lastTime = System.nanoTime();1015         final Node node = addWaiter(Node.SHARED);1016         boolean failed = true;1017         try {1018             for (;;) {1019                 final Node p = node.predecessor();1020                 if (p == head) {1021                     int r = tryAcquireShared(arg);1022                     if (r >= 0) {1023                         setHeadAndPropagate(node, r);1024                         p.next = null; // help GC1025                         failed = false;1026                         return true;1027                     }1028                 }1029                 if (nanosTimeout <= 0)1030                     return false;1031                 if (shouldParkAfterFailedAcquire(p, node) &&1032                     nanosTimeout > spinForTimeoutThreshold)1033                     LockSupport.parkNanos(this, nanosTimeout);1034                 long now = System.nanoTime();1035                 nanosTimeout -= now - lastTime;1036                 lastTime = now;1037                 if (Thread.interrupted())1038                     throw new InterruptedException();1039             }1040         } finally {1041             if (failed)1042                 cancelAcquire(node);1043         }1044     }1045 1046     // Main exported methods1047 1048     /**1049      * Attempts to acquire in exclusive mode. This method should query1050      * if the state of the object permits it to be acquired in the1051      * exclusive mode, and if so to acquire it.1052      *1053      * <p>This method is always invoked by the thread performing1054      * acquire.  If this method reports failure, the acquire method1055      * may queue the thread, if it is not already queued, until it is1056      * signalled by a release from some other thread. This can be used1057      * to implement method {@link Lock#tryLock()}.1058      *1059      * <p>The default1060      * implementation throws {@link UnsupportedOperationException}.1061      *1062      * @param arg the acquire argument. This value is always the one1063      *        passed to an acquire method, or is the value saved on entry1064      *        to a condition wait.  The value is otherwise uninterpreted1065      *        and can represent anything you like.1066      * @return {@code true} if successful. Upon success, this object has1067      *         been acquired.1068      * @throws IllegalMonitorStateException if acquiring would place this1069      *         synchronizer in an illegal state. This exception must be1070      *         thrown in a consistent fashion for synchronization to work1071      *         correctly.1072      * @throws UnsupportedOperationException if exclusive mode is not supported1073      */1074     protected boolean tryAcquire(int arg) {1075         throw new UnsupportedOperationException();1076     }1077 1078     /**1079      * Attempts to set the state to reflect a release in exclusive1080      * mode.1081      *1082      * <p>This method is always invoked by the thread performing release.1083      *1084      * <p>The default implementation throws1085      * {@link UnsupportedOperationException}.1086      *1087      * @param arg the release argument. This value is always the one1088      *        passed to a release method, or the current state value upon1089      *        entry to a condition wait.  The value is otherwise1090      *        uninterpreted and can represent anything you like.1091      * @return {@code true} if this object is now in a fully released1092      *         state, so that any waiting threads may attempt to acquire;1093      *         and {@code false} otherwise.1094      * @throws IllegalMonitorStateException if releasing would place this1095      *         synchronizer in an illegal state. This exception must be1096      *         thrown in a consistent fashion for synchronization to work1097      *         correctly.1098      * @throws UnsupportedOperationException if exclusive mode is not supported1099      */1100     protected boolean tryRelease(int arg) {1101         throw new UnsupportedOperationException();1102     }1103 1104     /**1105      * Attempts to acquire in shared mode. This method should query if1106      * the state of the object permits it to be acquired in the shared1107      * mode, and if so to acquire it.1108      *1109      * <p>This method is always invoked by the thread performing1110      * acquire.  If this method reports failure, the acquire method1111      * may queue the thread, if it is not already queued, until it is1112      * signalled by a release from some other thread.1113      *1114      * <p>The default implementation throws {@link1115      * UnsupportedOperationException}.1116      *1117      * @param arg the acquire argument. This value is always the one1118      *        passed to an acquire method, or is the value saved on entry1119      *        to a condition wait.  The value is otherwise uninterpreted1120      *        and can represent anything you like.1121      * @return a negative value on failure; zero if acquisition in shared1122      *         mode succeeded but no subsequent shared-mode acquire can1123      *         succeed; and a positive value if acquisition in shared1124      *         mode succeeded and subsequent shared-mode acquires might1125      *         also succeed, in which case a subsequent waiting thread1126      *         must check availability. (Support for three different1127      *         return values enables this method to be used in contexts1128      *         where acquires only sometimes act exclusively.)  Upon1129      *         success, this object has been acquired.1130      * @throws IllegalMonitorStateException if acquiring would place this1131      *         synchronizer in an illegal state. This exception must be1132      *         thrown in a consistent fashion for synchronization to work1133      *         correctly.1134      * @throws UnsupportedOperationException if shared mode is not supported1135      */1136     protected int tryAcquireShared(int arg) {1137         throw new UnsupportedOperationException();1138     }1139 1140     /**1141      * Attempts to set the state to reflect a release in shared mode.1142      *1143      * <p>This method is always invoked by the thread performing release.1144      *1145      * <p>The default implementation throws1146      * {@link UnsupportedOperationException}.1147      *1148      * @param arg the release argument. This value is always the one1149      *        passed to a release method, or the current state value upon1150      *        entry to a condition wait.  The value is otherwise1151      *        uninterpreted and can represent anything you like.1152      * @return {@code true} if this release of shared mode may permit a1153      *         waiting acquire (shared or exclusive) to succeed; and1154      *         {@code false} otherwise1155      * @throws IllegalMonitorStateException if releasing would place this1156      *         synchronizer in an illegal state. This exception must be1157      *         thrown in a consistent fashion for synchronization to work1158      *         correctly.1159      * @throws UnsupportedOperationException if shared mode is not supported1160      */1161     protected boolean tryReleaseShared(int arg) {1162         throw new UnsupportedOperationException();1163     }1164 1165     /**1166      * Returns {@code true} if synchronization is held exclusively with1167      * respect to the current (calling) thread.  This method is invoked1168      * upon each call to a non-waiting {@link ConditionObject} method.1169      * (Waiting methods instead invoke {@link #release}.)1170      *1171      * <p>The default implementation throws {@link1172      * UnsupportedOperationException}. This method is invoked1173      * internally only within {@link ConditionObject} methods, so need1174      * not be defined if conditions are not used.1175      *1176      * @return {@code true} if synchronization is held exclusively;1177      *         {@code false} otherwise1178      * @throws UnsupportedOperationException if conditions are not supported1179      */1180     protected boolean isHeldExclusively() {1181         throw new UnsupportedOperationException();1182     }1183 1184     /**1185      * Acquires in exclusive mode, ignoring interrupts.  Implemented1186      * by invoking at least once {@link #tryAcquire},1187      * returning on success.  Otherwise the thread is queued, possibly1188      * repeatedly blocking and unblocking, invoking {@link1189      * #tryAcquire} until success.  This method can be used1190      * to implement method {@link Lock#lock}.1191      *1192      * @param arg the acquire argument.  This value is conveyed to1193      *        {@link #tryAcquire} but is otherwise uninterpreted and1194      *        can represent anything you like.1195      */1196     public final void acquire(int arg) {1197         if (!tryAcquire(arg) &&1198             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))1199             selfInterrupt();1200     }1201 1202     /**1203      * Acquires in exclusive mode, aborting if interrupted.1204      * Implemented by first checking interrupt status, then invoking1205      * at least once {@link #tryAcquire}, returning on1206      * success.  Otherwise the thread is queued, possibly repeatedly1207      * blocking and unblocking, invoking {@link #tryAcquire}1208      * until success or the thread is interrupted.  This method can be1209      * used to implement method {@link Lock#lockInterruptibly}.1210      *1211      * @param arg the acquire argument.  This value is conveyed to1212      *        {@link #tryAcquire} but is otherwise uninterpreted and1213      *        can represent anything you like.1214      * @throws InterruptedException if the current thread is interrupted1215      */1216     public final void acquireInterruptibly(int arg)1217             throws InterruptedException {1218         if (Thread.interrupted())1219             throw new InterruptedException();1220         if (!tryAcquire(arg))1221             doAcquireInterruptibly(arg);1222     }1223 1224     /**1225      * Attempts to acquire in exclusive mode, aborting if interrupted,1226      * and failing if the given timeout elapses.  Implemented by first1227      * checking interrupt status, then invoking at least once {@link1228      * #tryAcquire}, returning on success.  Otherwise, the thread is1229      * queued, possibly repeatedly blocking and unblocking, invoking1230      * {@link #tryAcquire} until success or the thread is interrupted1231      * or the timeout elapses.  This method can be used to implement1232      * method {@link Lock#tryLock(long, TimeUnit)}.1233      *1234      * @param arg the acquire argument.  This value is conveyed to1235      *        {@link #tryAcquire} but is otherwise uninterpreted and1236      *        can represent anything you like.1237      * @param nanosTimeout the maximum number of nanoseconds to wait1238      * @return {@code true} if acquired; {@code false} if timed out1239      * @throws InterruptedException if the current thread is interrupted1240      */1241     public final boolean tryAcquireNanos(int arg, long nanosTimeout)1242             throws InterruptedException {1243         if (Thread.interrupted())1244             throw new InterruptedException();1245         return tryAcquire(arg) ||1246             doAcquireNanos(arg, nanosTimeout);1247     }1248 1249     /**1250      * Releases in exclusive mode.  Implemented by unblocking one or1251      * more threads if {@link #tryRelease} returns true.1252      * This method can be used to implement method {@link Lock#unlock}.1253      *1254      * @param arg the release argument.  This value is conveyed to1255      *        {@link #tryRelease} but is otherwise uninterpreted and1256      *        can represent anything you like.1257      * @return the value returned from {@link #tryRelease}1258      */1259     public final boolean release(int arg) {1260         if (tryRelease(arg)) {1261             Node h = head;1262             if (h != null && h.waitStatus != 0)1263                 unparkSuccessor(h);1264             return true;1265         }1266         return false;1267     }1268 1269     /**1270      * Acquires in shared mode, ignoring interrupts.  Implemented by1271      * first invoking at least once {@link #tryAcquireShared},1272      * returning on success.  Otherwise the thread is queued, possibly1273      * repeatedly blocking and unblocking, invoking {@link1274      * #tryAcquireShared} until success.1275      *1276      * @param arg the acquire argument.  This value is conveyed to1277      *        {@link #tryAcquireShared} but is otherwise uninterpreted1278      *        and can represent anything you like.1279      */1280     public final void acquireShared(int arg) {1281         if (tryAcquireShared(arg) < 0)1282             doAcquireShared(arg);1283     }1284 1285     /**1286      * Acquires in shared mode, aborting if interrupted.  Implemented1287      * by first checking interrupt status, then invoking at least once1288      * {@link #tryAcquireShared}, returning on success.  Otherwise the1289      * thread is queued, possibly repeatedly blocking and unblocking,1290      * invoking {@link #tryAcquireShared} until success or the thread1291      * is interrupted.1292      * @param arg the acquire argument1293      * This value is conveyed to {@link #tryAcquireShared} but is1294      * otherwise uninterpreted and can represent anything1295      * you like.1296      * @throws InterruptedException if the current thread is interrupted1297      */1298     public final void acquireSharedInterruptibly(int arg)1299             throws InterruptedException {1300         if (Thread.interrupted())1301             throw new InterruptedException();1302         if (tryAcquireShared(arg) < 0)1303             doAcquireSharedInterruptibly(arg);1304     }1305 1306     /**1307      * Attempts to acquire in shared mode, aborting if interrupted, and1308      * failing if the given timeout elapses.  Implemented by first1309      * checking interrupt status, then invoking at least once {@link1310      * #tryAcquireShared}, returning on success.  Otherwise, the1311      * thread is queued, possibly repeatedly blocking and unblocking,1312      * invoking {@link #tryAcquireShared} until success or the thread1313      * is interrupted or the timeout elapses.1314      *1315      * @param arg the acquire argument.  This value is conveyed to1316      *        {@link #tryAcquireShared} but is otherwise uninterpreted1317      *        and can represent anything you like.1318      * @param nanosTimeout the maximum number of nanoseconds to wait1319      * @return {@code true} if acquired; {@code false} if timed out1320      * @throws InterruptedException if the current thread is interrupted1321      */1322     public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)1323             throws InterruptedException {1324         if (Thread.interrupted())1325             throw new InterruptedException();1326         return tryAcquireShared(arg) >= 0 ||1327             doAcquireSharedNanos(arg, nanosTimeout);1328     }1329 1330     /**1331      * Releases in shared mode.  Implemented by unblocking one or more1332      * threads if {@link #tryReleaseShared} returns true.1333      *1334      * @param arg the release argument.  This value is conveyed to1335      *        {@link #tryReleaseShared} but is otherwise uninterpreted1336      *        and can represent anything you like.1337      * @return the value returned from {@link #tryReleaseShared}1338      */1339     public final boolean releaseShared(int arg) {1340         if (tryReleaseShared(arg)) {1341             doReleaseShared();1342             return true;1343         }1344         return false;1345     }1346 1347     // Queue inspection methods1348 1349     /**1350      * Queries whether any threads are waiting to acquire. Note that1351      * because cancellations due to interrupts and timeouts may occur1352      * at any time, a {@code true} return does not guarantee that any1353      * other thread will ever acquire.1354      *1355      * <p>In this implementation, this operation returns in1356      * constant time.1357      *1358      * @return {@code true} if there may be other threads waiting to acquire1359      */1360     public final boolean hasQueuedThreads() {1361         return head != tail;1362     }1363 1364     /**1365      * Queries whether any threads have ever contended to acquire this1366      * synchronizer; that is if an acquire method has ever blocked.1367      *1368      * <p>In this implementation, this operation returns in1369      * constant time.1370      *1371      * @return {@code true} if there has ever been contention1372      */1373     public final boolean hasContended() {1374         return head != null;1375     }1376 1377     /**1378      * Returns the first (longest-waiting) thread in the queue, or1379      * {@code null} if no threads are currently queued.1380      *1381      * <p>In this implementation, this operation normally returns in1382      * constant time, but may iterate upon contention if other threads are1383      * concurrently modifying the queue.1384      *1385      * @return the first (longest-waiting) thread in the queue, or1386      *         {@code null} if no threads are currently queued1387      */1388     public final Thread getFirstQueuedThread() {1389         // handle only fast path, else relay1390         return (head == tail) ? null : fullGetFirstQueuedThread();1391     }1392 1393     /**1394      * Version of getFirstQueuedThread called when fastpath fails1395      */1396     private Thread fullGetFirstQueuedThread() {1397         /*1398          * The first node is normally head.next. Try to get its1399          * thread field, ensuring consistent reads: If thread1400          * field is nulled out or s.prev is no longer head, then1401          * some other thread(s) concurrently performed setHead in1402          * between some of our reads. We try this twice before1403          * resorting to traversal.1404          */1405         Node h, s;1406         Thread st;1407         if (((h = head) != null && (s = h.next) != null &&1408              s.prev == head && (st = s.thread) != null) ||1409             ((h = head) != null && (s = h.next) != null &&1410              s.prev == head && (st = s.thread) != null))1411             return st;1412 1413         /*1414          * Head's next field might not have been set yet, or may have1415          * been unset after setHead. So we must check to see if tail1416          * is actually first node. If not, we continue on, safely1417          * traversing from tail back to head to find first,1418          * guaranteeing termination.1419          */1420 1421         Node t = tail;1422         Thread firstThread = null;1423         while (t != null && t != head) {1424             Thread tt = t.thread;1425             if (tt != null)1426                 firstThread = tt;1427             t = t.prev;1428         }1429         return firstThread;1430     }1431 1432     /**1433      * Returns true if the given thread is currently queued.1434      *1435      * <p>This implementation traverses the queue to determine1436      * presence of the given thread.1437      *1438      * @param thread the thread1439      * @return {@code true} if the given thread is on the queue1440      * @throws NullPointerException if the thread is null1441      */1442     public final boolean isQueued(Thread thread) {1443         if (thread == null)1444             throw new NullPointerException();1445         for (Node p = tail; p != null; p = p.prev)1446             if (p.thread == thread)1447                 return true;1448         return false;1449     }1450 1451     /**1452      * Returns {@code true} if the apparent first queued thread, if one1453      * exists, is waiting in exclusive mode.  If this method returns1454      * {@code true}, and the current thread is attempting to acquire in1455      * shared mode (that is, this method is invoked from {@link1456      * #tryAcquireShared}) then it is guaranteed that the current thread1457      * is not the first queued thread.  Used only as a heuristic in1458      * ReentrantReadWriteLock.1459      */1460     final boolean apparentlyFirstQueuedIsExclusive() {1461         Node h, s;1462         return (h = head) != null &&1463             (s = h.next)  != null &&1464             !s.isShared()         &&1465             s.thread != null;1466     }1467 1468     /**1469      * Queries whether any threads have been waiting to acquire longer1470      * than the current thread.1471      *1472      * <p>An invocation of this method is equivalent to (but may be1473      * more efficient than):1474      *  <pre> {@code1475      * getFirstQueuedThread() != Thread.currentThread() &&1476      * hasQueuedThreads()}</pre>1477      *1478      * <p>Note that because cancellations due to interrupts and1479      * timeouts may occur at any time, a {@code true} return does not1480      * guarantee that some other thread will acquire before the current1481      * thread.  Likewise, it is possible for another thread to win a1482      * race to enqueue after this method has returned {@code false},1483      * due to the queue being empty.1484      *1485      * <p>This method is designed to be used by a fair synchronizer to1486      * avoid <a href="AbstractQueuedSynchronizer#barging">barging</a>.1487      * Such a synchronizer's {@link #tryAcquire} method should return1488      * {@code false}, and its {@link #tryAcquireShared} method should1489      * return a negative value, if this method returns {@code true}1490      * (unless this is a reentrant acquire).  For example, the {@code1491      * tryAcquire} method for a fair, reentrant, exclusive mode1492      * synchronizer might look like this:1493      *1494      *  <pre> {@code1495      * protected boolean tryAcquire(int arg) {1496      *   if (isHeldExclusively()) {1497      *     // A reentrant acquire; increment hold count1498      *     return true;1499      *   } else if (hasQueuedPredecessors()) {1500      *     return false;1501      *   } else {1502      *     // try to acquire normally1503      *   }1504      * }}</pre>1505      *1506      * @return {@code true} if there is a queued thread preceding the1507      *         current thread, and {@code false} if the current thread1508      *         is at the head of the queue or the queue is empty1509      * @since 1.71510      */1511     public final boolean hasQueuedPredecessors() {1512         // The correctness of this depends on head being initialized1513         // before tail and on head.next being accurate if the current1514         // thread is first in queue.1515         Node t = tail; // Read fields in reverse initialization order1516         Node h = head;1517         Node s;1518         return h != t &&1519             ((s = h.next) == null || s.thread != Thread.currentThread());1520     }1521 1522 1523     // Instrumentation and monitoring methods1524 1525     /**1526      * Returns an estimate of the number of threads waiting to1527      * acquire.  The value is only an estimate because the number of1528      * threads may change dynamically while this method traverses1529      * internal data structures.  This method is designed for use in1530      * monitoring system state, not for synchronization1531      * control.1532      *1533      * @return the estimated number of threads waiting to acquire1534      */1535     public final int getQueueLength() {1536         int n = 0;1537         for (Node p = tail; p != null; p = p.prev) {1538             if (p.thread != null)1539                 ++n;1540         }1541         return n;1542     }1543 1544     /**1545      * Returns a collection containing threads that may be waiting to1546      * acquire.  Because the actual set of threads may change1547      * dynamically while constructing this result, the returned1548      * collection is only a best-effort estimate.  The elements of the1549      * returned collection are in no particular order.  This method is1550      * designed to facilitate construction of subclasses that provide1551      * more extensive monitoring facilities.1552      *1553      * @return the collection of threads1554      */1555     public final Collection<Thread> getQueuedThreads() {1556         ArrayList<Thread> list = new ArrayList<Thread>();1557         for (Node p = tail; p != null; p = p.prev) {1558             Thread t = p.thread;1559             if (t != null)1560                 list.add(t);1561         }1562         return list;1563     }1564 1565     /**1566      * Returns a collection containing threads that may be waiting to1567      * acquire in exclusive mode. This has the same properties1568      * as {@link #getQueuedThreads} except that it only returns1569      * those threads waiting due to an exclusive acquire.1570      *1571      * @return the collection of threads1572      */1573     public final Collection<Thread> getExclusiveQueuedThreads() {1574         ArrayList<Thread> list = new ArrayList<Thread>();1575         for (Node p = tail; p != null; p = p.prev) {1576             if (!p.isShared()) {1577                 Thread t = p.thread;1578                 if (t != null)1579                     list.add(t);1580             }1581         }1582         return list;1583     }1584 1585     /**1586      * Returns a collection containing threads that may be waiting to1587      * acquire in shared mode. This has the same properties1588      * as {@link #getQueuedThreads} except that it only returns1589      * those threads waiting due to a shared acquire.1590      *1591      * @return the collection of threads1592      */1593     public final Collection<Thread> getSharedQueuedThreads() {1594         ArrayList<Thread> list = new ArrayList<Thread>();1595         for (Node p = tail; p != null; p = p.prev) {1596             if (p.isShared()) {1597                 Thread t = p.thread;1598                 if (t != null)1599                     list.add(t);1600             }1601         }1602         return list;1603     }1604 1605     /**1606      * Returns a string identifying this synchronizer, as well as its state.1607      * The state, in brackets, includes the String {@code "State ="}1608      * followed by the current value of {@link #getState}, and either1609      * {@code "nonempty"} or {@code "empty"} depending on whether the1610      * queue is empty.1611      *1612      * @return a string identifying this synchronizer, as well as its state1613      */1614     public String toString() {1615         int s = getState();1616         String q  = hasQueuedThreads() ? "non" : "";1617         return super.toString() +1618             "[State = " + s + ", " + q + "empty queue]";1619     }1620 1621 1622     // Internal support methods for Conditions1623 1624     /**1625      * Returns true if a node, always one that was initially placed on1626      * a condition queue, is now waiting to reacquire on sync queue.1627      * @param node the node1628      * @return true if is reacquiring1629      */1630     final boolean isOnSyncQueue(Node node) {1631         if (node.waitStatus == Node.CONDITION || node.prev == null)1632             return false;1633         if (node.next != null) // If has successor, it must be on queue1634             return true;1635         /*1636          * node.prev can be non-null, but not yet on queue because1637          * the CAS to place it on queue can fail. So we have to1638          * traverse from tail to make sure it actually made it.  It1639          * will always be near the tail in calls to this method, and1640          * unless the CAS failed (which is unlikely), it will be1641          * there, so we hardly ever traverse much.1642          */1643         return findNodeFromTail(node);1644     }1645 1646     /**1647      * Returns true if node is on sync queue by searching backwards from tail.1648      * Called only when needed by isOnSyncQueue.1649      * @return true if present1650      */1651     private boolean findNodeFromTail(Node node) {1652         Node t = tail;1653         for (;;) {1654             if (t == node)1655                 return true;1656             if (t == null)1657                 return false;1658             t = t.prev;1659         }1660     }1661 1662     /**1663      * Transfers a node from a condition queue onto sync queue.1664      * Returns true if successful.1665      * @param node the node1666      * @return true if successfully transferred (else the node was1667      * cancelled before signal).1668      */1669     final boolean transferForSignal(Node node) {1670         /*1671          * If cannot change waitStatus, the node has been cancelled.1672          */1673         if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))1674             return false;1675 1676         /*1677          * Splice onto queue and try to set waitStatus of predecessor to1678          * indicate that thread is (probably) waiting. If cancelled or1679          * attempt to set waitStatus fails, wake up to resync (in which1680          * case the waitStatus can be transiently and harmlessly wrong).1681          */1682         Node p = enq(node);1683         int ws = p.waitStatus;1684         if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))1685             LockSupport.unpark(node.thread);1686         return true;1687     }1688 1689     /**1690      * Transfers node, if necessary, to sync queue after a cancelled1691      * wait. Returns true if thread was cancelled before being1692      * signalled.1693      * @param current the waiting thread1694      * @param node its node1695      * @return true if cancelled before the node was signalled1696      */1697     final boolean transferAfterCancelledWait(Node node) {1698         if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {1699             enq(node);1700             return true;1701         }1702         /*1703          * If we lost out to a signal(), then we can't proceed1704          * until it finishes its enq().  Cancelling during an1705          * incomplete transfer is both rare and transient, so just1706          * spin.1707          */1708         while (!isOnSyncQueue(node))1709             Thread.yield();1710         return false;1711     }1712 1713     /**1714      * Invokes release with current state value; returns saved state.1715      * Cancels node and throws exception on failure.1716      * @param node the condition node for this wait1717      * @return previous sync state1718      */1719     final int fullyRelease(Node node) {1720         boolean failed = true;1721         try {1722             int savedState = getState();1723             if (release(savedState)) {1724                 failed = false;1725                 return savedState;1726             } else {1727                 throw new IllegalMonitorStateException();1728             }1729         } finally {1730             if (failed)1731                 node.waitStatus = Node.CANCELLED;1732         }1733     }1734 1735     // Instrumentation methods for conditions1736 1737     /**1738      * Queries whether the given ConditionObject1739      * uses this synchronizer as its lock.1740      *1741      * @param condition the condition1742      * @return <tt>true</tt> if owned1743      * @throws NullPointerException if the condition is null1744      */1745     public final boolean owns(ConditionObject condition) {1746         if (condition == null)1747             throw new NullPointerException();1748         return condition.isOwnedBy(this);1749     }1750 1751     /**1752      * Queries whether any threads are waiting on the given condition1753      * associated with this synchronizer. Note that because timeouts1754      * and interrupts may occur at any time, a <tt>true</tt> return1755      * does not guarantee that a future <tt>signal</tt> will awaken1756      * any threads.  This method is designed primarily for use in1757      * monitoring of the system state.1758      *1759      * @param condition the condition1760      * @return <tt>true</tt> if there are any waiting threads1761      * @throws IllegalMonitorStateException if exclusive synchronization1762      *         is not held1763      * @throws IllegalArgumentException if the given condition is1764      *         not associated with this synchronizer1765      * @throws NullPointerException if the condition is null1766      */1767     public final boolean hasWaiters(ConditionObject condition) {1768         if (!owns(condition))1769             throw new IllegalArgumentException("Not owner");1770         return condition.hasWaiters();1771     }1772 1773     /**1774      * Returns an estimate of the number of threads waiting on the1775      * given condition associated with this synchronizer. Note that1776      * because timeouts and interrupts may occur at any time, the1777      * estimate serves only as an upper bound on the actual number of1778      * waiters.  This method is designed for use in monitoring of the1779      * system state, not for synchronization control.1780      *1781      * @param condition the condition1782      * @return the estimated number of waiting threads1783      * @throws IllegalMonitorStateException if exclusive synchronization1784      *         is not held1785      * @throws IllegalArgumentException if the given condition is1786      *         not associated with this synchronizer1787      * @throws NullPointerException if the condition is null1788      */1789     public final int getWaitQueueLength(ConditionObject condition) {1790         if (!owns(condition))1791             throw new IllegalArgumentException("Not owner");1792         return condition.getWaitQueueLength();1793     }1794 1795     /**1796      * Returns a collection containing those threads that may be1797      * waiting on the given condition associated with this1798      * synchronizer.  Because the actual set of threads may change1799      * dynamically while constructing this result, the returned1800      * collection is only a best-effort estimate. The elements of the1801      * returned collection are in no particular order.1802      *1803      * @param condition the condition1804      * @return the collection of threads1805      * @throws IllegalMonitorStateException if exclusive synchronization1806      *         is not held1807      * @throws IllegalArgumentException if the given condition is1808      *         not associated with this synchronizer1809      * @throws NullPointerException if the condition is null1810      */1811     public final Collection<Thread> getWaitingThreads(ConditionObject condition) {1812         if (!owns(condition))1813             throw new IllegalArgumentException("Not owner");1814         return condition.getWaitingThreads();1815     }1816 1817     /**1818      * Condition implementation for a {@link1819      * AbstractQueuedSynchronizer} serving as the basis of a {@link1820      * Lock} implementation.1821      *1822      * <p>Method documentation for this class describes mechanics,1823      * not behavioral specifications from the point of view of Lock1824      * and Condition users. Exported versions of this class will in1825      * general need to be accompanied by documentation describing1826      * condition semantics that rely on those of the associated1827      * <tt>AbstractQueuedSynchronizer</tt>.1828      *1829      * <p>This class is Serializable, but all fields are transient,1830      * so deserialized conditions have no waiters.1831      */1832     public class ConditionObject implements Condition, java.io.Serializable {1833         private static final long serialVersionUID = 1173984872572414699L;1834         /** First node of condition queue. */1835         private transient Node firstWaiter;1836         /** Last node of condition queue. */1837         private transient Node lastWaiter;1838 1839         /**1840          * Creates a new <tt>ConditionObject</tt> instance.1841          */1842         public ConditionObject() { }1843 1844         // Internal methods1845 1846         /**1847          * Adds a new waiter to wait queue.1848          * @return its new wait node1849          */1850         private Node addConditionWaiter() {1851             Node t = lastWaiter;1852             // If lastWaiter is cancelled, clean out.1853             if (t != null && t.waitStatus != Node.CONDITION) {1854                 unlinkCancelledWaiters();1855                 t = lastWaiter;1856             }1857             Node node = new Node(Thread.currentThread(), Node.CONDITION);1858             if (t == null)1859                 firstWaiter = node;1860             else1861                 t.nextWaiter = node;1862             lastWaiter = node;1863             return node;1864         }1865 1866         /**1867          * Removes and transfers nodes until hit non-cancelled one or1868          * null. Split out from signal in part to encourage compilers1869          * to inline the case of no waiters.1870          * @param first (non-null) the first node on condition queue1871          */1872         private void doSignal(Node first) {1873             do {1874                 if ( (firstWaiter = first.nextWaiter) == null)1875                     lastWaiter = null;1876                 first.nextWaiter = null;1877             } while (!transferForSignal(first) &&1878                      (first = firstWaiter) != null);1879         }1880 1881         /**1882          * Removes and transfers all nodes.1883          * @param first (non-null) the first node on condition queue1884          */1885         private void doSignalAll(Node first) {1886             lastWaiter = firstWaiter = null;1887             do {1888                 Node next = first.nextWaiter;1889                 first.nextWaiter = null;1890                 transferForSignal(first);1891                 first = next;1892             } while (first != null);1893         }1894 1895         /**1896          * Unlinks cancelled waiter nodes from condition queue.1897          * Called only while holding lock. This is called when1898          * cancellation occurred during condition wait, and upon1899          * insertion of a new waiter when lastWaiter is seen to have1900          * been cancelled. This method is needed to avoid garbage1901          * retention in the absence of signals. So even though it may1902          * require a full traversal, it comes into play only when1903          * timeouts or cancellations occur in the absence of1904          * signals. It traverses all nodes rather than stopping at a1905          * particular target to unlink all pointers to garbage nodes1906          * without requiring many re-traversals during cancellation1907          * storms.1908          */1909         private void unlinkCancelledWaiters() {1910             Node t = firstWaiter;1911             Node trail = null;1912             while (t != null) {1913                 Node next = t.nextWaiter;1914                 if (t.waitStatus != Node.CONDITION) {1915                     t.nextWaiter = null;1916                     if (trail == null)1917                         firstWaiter = next;1918                     else1919                         trail.nextWaiter = next;1920                     if (next == null)1921                         lastWaiter = trail;1922                 }1923                 else1924                     trail = t;1925                 t = next;1926             }1927         }1928 1929         // public methods1930 1931         /**1932          * Moves the longest-waiting thread, if one exists, from the1933          * wait queue for this condition to the wait queue for the1934          * owning lock.1935          *1936          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}1937          *         returns {@code false}1938          */1939         public final void signal() {1940             if (!isHeldExclusively())1941                 throw new IllegalMonitorStateException();1942             Node first = firstWaiter;1943             if (first != null)1944                 doSignal(first);1945         }1946 1947         /**1948          * Moves all threads from the wait queue for this condition to1949          * the wait queue for the owning lock.1950          *1951          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}1952          *         returns {@code false}1953          */1954         public final void signalAll() {1955             if (!isHeldExclusively())1956                 throw new IllegalMonitorStateException();1957             Node first = firstWaiter;1958             if (first != null)1959                 doSignalAll(first);1960         }1961 1962         /**1963          * Implements uninterruptible condition wait.1964          * <ol>1965          * <li> Save lock state returned by {@link #getState}.1966          * <li> Invoke {@link #release} with1967          *      saved state as argument, throwing1968          *      IllegalMonitorStateException if it fails.1969          * <li> Block until signalled.1970          * <li> Reacquire by invoking specialized version of1971          *      {@link #acquire} with saved state as argument.1972          * </ol>1973          */1974         public final void awaitUninterruptibly() {1975             Node node = addConditionWaiter();1976             int savedState = fullyRelease(node);1977             boolean interrupted = false;1978             while (!isOnSyncQueue(node)) {1979                 LockSupport.park(this);1980                 if (Thread.interrupted())1981                     interrupted = true;1982             }1983             if (acquireQueued(node, savedState) || interrupted)1984                 selfInterrupt();1985         }1986 1987         /*1988          * For interruptible waits, we need to track whether to throw1989          * InterruptedException, if interrupted while blocked on1990          * condition, versus reinterrupt current thread, if1991          * interrupted while blocked waiting to re-acquire.1992          */1993 1994         /** Mode meaning to reinterrupt on exit from wait */1995         private static final int REINTERRUPT =  1;1996         /** Mode meaning to throw InterruptedException on exit from wait */1997         private static final int THROW_IE    = -1;1998 1999         /**2000          * Checks for interrupt, returning THROW_IE if interrupted2001          * before signalled, REINTERRUPT if after signalled, or2002          * 0 if not interrupted.2003          */2004         private int checkInterruptWhileWaiting(Node node) {2005             return Thread.interrupted() ?2006                 (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :2007                 0;2008         }2009 2010         /**2011          * Throws InterruptedException, reinterrupts current thread, or2012          * does nothing, depending on mode.2013          */2014         private void reportInterruptAfterWait(int interruptMode)2015             throws InterruptedException {2016             if (interruptMode == THROW_IE)2017                 throw new InterruptedException();2018             else if (interruptMode == REINTERRUPT)2019                 selfInterrupt();2020         }2021 2022         /**2023          * Implements interruptible condition wait.2024          * <ol>2025          * <li> If current thread is interrupted, throw InterruptedException.2026          * <li> Save lock state returned by {@link #getState}.2027          * <li> Invoke {@link #release} with2028          *      saved state as argument, throwing2029          *      IllegalMonitorStateException if it fails.2030          * <li> Block until signalled or interrupted.2031          * <li> Reacquire by invoking specialized version of2032          *      {@link #acquire} with saved state as argument.2033          * <li> If interrupted while blocked in step 4, throw InterruptedException.2034          * </ol>2035          */2036         public final void await() throws InterruptedException {2037             if (Thread.interrupted())2038                 throw new InterruptedException();2039             Node node = addConditionWaiter();2040             int savedState = fullyRelease(node);2041             int interruptMode = 0;2042             while (!isOnSyncQueue(node)) {2043                 LockSupport.park(this);2044                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)2045                     break;2046             }2047             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)2048                 interruptMode = REINTERRUPT;2049             if (node.nextWaiter != null) // clean up if cancelled2050                 unlinkCancelledWaiters();2051             if (interruptMode != 0)2052                 reportInterruptAfterWait(interruptMode);2053         }2054 2055         /**2056          * Implements timed condition wait.2057          * <ol>2058          * <li> If current thread is interrupted, throw InterruptedException.2059          * <li> Save lock state returned by {@link #getState}.2060          * <li> Invoke {@link #release} with2061          *      saved state as argument, throwing2062          *      IllegalMonitorStateException if it fails.2063          * <li> Block until signalled, interrupted, or timed out.2064          * <li> Reacquire by invoking specialized version of2065          *      {@link #acquire} with saved state as argument.2066          * <li> If interrupted while blocked in step 4, throw InterruptedException.2067          * </ol>2068          */2069         public final long awaitNanos(long nanosTimeout)2070                 throws InterruptedException {2071             if (Thread.interrupted())2072                 throw new InterruptedException();2073             Node node = addConditionWaiter();2074             int savedState = fullyRelease(node);2075             long lastTime = System.nanoTime();2076             int interruptMode = 0;2077             while (!isOnSyncQueue(node)) {2078                 if (nanosTimeout <= 0L) {2079                     transferAfterCancelledWait(node);2080                     break;2081                 }2082                 LockSupport.parkNanos(this, nanosTimeout);2083                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)2084                     break;2085 2086                 long now = System.nanoTime();2087                 nanosTimeout -= now - lastTime;2088                 lastTime = now;2089             }2090             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)2091                 interruptMode = REINTERRUPT;2092             if (node.nextWaiter != null)2093                 unlinkCancelledWaiters();2094             if (interruptMode != 0)2095                 reportInterruptAfterWait(interruptMode);2096             return nanosTimeout - (System.nanoTime() - lastTime);2097         }2098 2099         /**2100          * Implements absolute timed condition wait.2101          * <ol>2102          * <li> If current thread is interrupted, throw InterruptedException.2103          * <li> Save lock state returned by {@link #getState}.2104          * <li> Invoke {@link #release} with2105          *      saved state as argument, throwing2106          *      IllegalMonitorStateException if it fails.2107          * <li> Block until signalled, interrupted, or timed out.2108          * <li> Reacquire by invoking specialized version of2109          *      {@link #acquire} with saved state as argument.2110          * <li> If interrupted while blocked in step 4, throw InterruptedException.2111          * <li> If timed out while blocked in step 4, return false, else true.2112          * </ol>2113          */2114         public final boolean awaitUntil(Date deadline)2115                 throws InterruptedException {2116             if (deadline == null)2117                 throw new NullPointerException();2118             long abstime = deadline.getTime();2119             if (Thread.interrupted())2120                 throw new InterruptedException();2121             Node node = addConditionWaiter();2122             int savedState = fullyRelease(node);2123             boolean timedout = false;2124             int interruptMode = 0;2125             while (!isOnSyncQueue(node)) {2126                 if (System.currentTimeMillis() > abstime) {2127                     timedout = transferAfterCancelledWait(node);2128                     break;2129                 }2130                 LockSupport.parkUntil(this, abstime);2131                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)2132                     break;2133             }2134             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)2135                 interruptMode = REINTERRUPT;2136             if (node.nextWaiter != null)2137                 unlinkCancelledWaiters();2138             if (interruptMode != 0)2139                 reportInterruptAfterWait(interruptMode);2140             return !timedout;2141         }2142 2143         /**2144          * Implements timed condition wait.2145          * <ol>2146          * <li> If current thread is interrupted, throw InterruptedException.2147          * <li> Save lock state returned by {@link #getState}.2148          * <li> Invoke {@link #release} with2149          *      saved state as argument, throwing2150          *      IllegalMonitorStateException if it fails.2151          * <li> Block until signalled, interrupted, or timed out.2152          * <li> Reacquire by invoking specialized version of2153          *      {@link #acquire} with saved state as argument.2154          * <li> If interrupted while blocked in step 4, throw InterruptedException.2155          * <li> If timed out while blocked in step 4, return false, else true.2156          * </ol>2157          */2158         public final boolean await(long time, TimeUnit unit)2159                 throws InterruptedException {2160             if (unit == null)2161                 throw new NullPointerException();2162             long nanosTimeout = unit.toNanos(time);2163             if (Thread.interrupted())2164                 throw new InterruptedException();2165             Node node = addConditionWaiter();2166             int savedState = fullyRelease(node);2167             long lastTime = System.nanoTime();2168             boolean timedout = false;2169             int interruptMode = 0;2170             while (!isOnSyncQueue(node)) {2171                 if (nanosTimeout <= 0L) {2172                     timedout = transferAfterCancelledWait(node);2173                     break;2174                 }2175                 if (nanosTimeout >= spinForTimeoutThreshold)2176                     LockSupport.parkNanos(this, nanosTimeout);2177                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)2178                     break;2179                 long now = System.nanoTime();2180                 nanosTimeout -= now - lastTime;2181                 lastTime = now;2182             }2183             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)2184                 interruptMode = REINTERRUPT;2185             if (node.nextWaiter != null)2186                 unlinkCancelledWaiters();2187             if (interruptMode != 0)2188                 reportInterruptAfterWait(interruptMode);2189             return !timedout;2190         }2191 2192         //  support for instrumentation2193 2194         /**2195          * Returns true if this condition was created by the given2196          * synchronization object.2197          *2198          * @return {@code true} if owned2199          */2200         final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {2201             return sync == AbstractQueuedSynchronizer.this;2202         }2203 2204         /**2205          * Queries whether any threads are waiting on this condition.2206          * Implements {@link AbstractQueuedSynchronizer#hasWaiters}.2207          *2208          * @return {@code true} if there are any waiting threads2209          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}2210          *         returns {@code false}2211          */2212         protected final boolean hasWaiters() {2213             if (!isHeldExclusively())2214                 throw new IllegalMonitorStateException();2215             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {2216                 if (w.waitStatus == Node.CONDITION)2217                     return true;2218             }2219             return false;2220         }2221 2222         /**2223          * Returns an estimate of the number of threads waiting on2224          * this condition.2225          * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength}.2226          *2227          * @return the estimated number of waiting threads2228          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}2229          *         returns {@code false}2230          */2231         protected final int getWaitQueueLength() {2232             if (!isHeldExclusively())2233                 throw new IllegalMonitorStateException();2234             int n = 0;2235             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {2236                 if (w.waitStatus == Node.CONDITION)2237                     ++n;2238             }2239             return n;2240         }2241 2242         /**2243          * Returns a collection containing those threads that may be2244          * waiting on this Condition.2245          * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads}.2246          *2247          * @return the collection of threads2248          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}2249          *         returns {@code false}2250          */2251         protected final Collection<Thread> getWaitingThreads() {2252             if (!isHeldExclusively())2253                 throw new IllegalMonitorStateException();2254             ArrayList<Thread> list = new ArrayList<Thread>();2255             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {2256                 if (w.waitStatus == Node.CONDITION) {2257                     Thread t = w.thread;2258                     if (t != null)2259                         list.add(t);2260                 }2261             }2262             return list;2263         }2264     }2265 2266     /**2267      * Setup to support compareAndSet. We need to natively implement2268      * this here: For the sake of permitting future enhancements, we2269      * cannot explicitly subclass AtomicInteger, which would be2270      * efficient and useful otherwise. So, as the lesser of evils, we2271      * natively implement using hotspot intrinsics API. And while we2272      * are at it, we do the same for other CASable fields (which could2273      * otherwise be done with atomic field updaters).2274      */2275     private static final Unsafe unsafe = Unsafe.getUnsafe();2276     private static final long stateOffset;2277     private static final long headOffset;2278     private static final long tailOffset;2279     private static final long waitStatusOffset;2280     private static final long nextOffset;2281 2282     static {2283         try {2284             stateOffset = unsafe.objectFieldOffset2285                 (AbstractQueuedSynchronizer.class.getDeclaredField("state"));2286             headOffset = unsafe.objectFieldOffset2287                 (AbstractQueuedSynchronizer.class.getDeclaredField("head"));2288             tailOffset = unsafe.objectFieldOffset2289                 (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));2290             waitStatusOffset = unsafe.objectFieldOffset2291                 (Node.class.getDeclaredField("waitStatus"));2292             nextOffset = unsafe.objectFieldOffset2293                 (Node.class.getDeclaredField("next"));2294 2295         } catch (Exception ex) { throw new Error(ex); }2296     }2297 2298     /**2299      * CAS head field. Used only by enq.2300      */2301     private final boolean compareAndSetHead(Node update) {2302         return unsafe.compareAndSwapObject(this, headOffset, null, update);2303     }2304 2305     /**2306      * CAS tail field. Used only by enq.2307      */2308     private final boolean compareAndSetTail(Node expect, Node update) {2309         return unsafe.compareAndSwapObject(this, tailOffset, expect, update);2310     }2311 2312     /**2313      * CAS waitStatus field of a node.2314      */2315     private static final boolean compareAndSetWaitStatus(Node node,2316                                                          int expect,2317                                                          int update) {2318         return unsafe.compareAndSwapInt(node, waitStatusOffset,2319                                         expect, update);2320     }2321 2322     /**2323      * CAS next field of a node.2324      */2325     private static final boolean compareAndSetNext(Node node,2326                                                    Node expect,2327                                                    Node update) {2328         return unsafe.compareAndSwapObject(node, nextOffset, expect, update);2329     }2330 }
复制代码

 

获取公平锁(基于JDK1.7.0_40)

通过前面“Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock”的“示例1”,我们知道,获取锁是通过lock()函数。下面,我们以lock()对获取公平锁的过程进行展开。

1. lock()

lock()在ReentrantLock.java的FairSync类中实现,它的源码如下:

final void lock() {    acquire(1);}

说明:“当前线程”实际上是通过acquire(1)获取锁的。
        这里说明一下“1”的含义,它是设置“锁的状态”的参数。对于“独占锁”而言,锁处于可获取状态时,它的状态值是0;锁被线程初次获取到了,它的状态值就变成了1。
        由于ReentrantLock(公平锁/非公平锁)是可重入锁,所以“独占锁”可以被单个线程多此获取,每获取1次就将锁的状态+1。也就是说,初次获取锁时,通过acquire(1)将锁的状态值设为1;再次获取锁时,将锁的状态值设为2;依次类推...这就是为什么获取锁时,传入的参数是1的原因了。
        可重入就是指锁可以被单个线程多次获取。

 

2. acquire()

acquire()在AQS中实现的,它的源码如下:

public final void acquire(int arg) {    if (!tryAcquire(arg) &&        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))        selfInterrupt();}

(01) “当前线程”首先通过tryAcquire()尝试获取锁。获取成功的话,直接返回;尝试失败的话,进入到等待队列排序等待(前面还有可能有需要线程在等待该锁)。
(02) “当前线程”尝试失败的情况下,先通过addWaiter(Node.EXCLUSIVE)来将“当前线程”加入到"CLH队列(非阻塞的FIFO队列)"末尾。CLH队列就是线程等待队列。
(03) 再执行完addWaiter(Node.EXCLUSIVE)之后,会调用acquireQueued()来获取锁。由于此时ReentrantLock是公平锁,它会根据公平性原则来获取锁。
(04) “当前线程”在执行acquireQueued()时,会
进入到CLH队列中休眠等待,直到获取锁了才返回!如果“当前线程”在休眠等待过程中被中断过,acquireQueued会返回true,此时"当前线程"会调用selfInterrupt()来自己给自己产生一个中断。至于为什么要自己给自己产生一个中断,后面再介绍。

上面是对acquire()的概括性说明。下面,我们将该函数分为4部分来逐步解析。
一. tryAcquire()
二. addWaiter()
三. acquireQueued()
四. selfInterrupt()

 

一. tryAcquire()

1. tryAcquire()

公平锁的tryAcquire()在ReentrantLock.java的FairSync类中实现,源码如下:

复制代码
protected final boolean tryAcquire(int acquires) {    // 获取“当前线程”    final Thread current = Thread.currentThread();    // 获取“独占锁”的状态    int c = getState();    // c=0意味着“锁没有被任何线程锁拥有”,    if (c == 0) {        // 若“锁没有被任何线程锁拥有”,        // 则判断“当前线程”是不是CLH队列中的第一个线程线程,        // 若是的话,则获取该锁,设置锁的状态,并切设置锁的拥有者为“当前线程”。        if (!hasQueuedPredecessors() &&            compareAndSetState(0, acquires)) {            setExclusiveOwnerThread(current);            return true;        }    }    else if (current == getExclusiveOwnerThread()) {        // 如果“独占锁”的拥有者已经为“当前线程”,        // 则将更新锁的状态。        int nextc = c + acquires;        if (nextc < 0)            throw new Error("Maximum lock count exceeded");        setState(nextc);        return true;    }    return false;}
复制代码

说明根据代码,我们可以分析出,tryAcquire()的作用就是尝试去获取锁。注意,这里只是尝试!
         尝试成功的话,返回true;尝试失败的话,返回false,后续再通过其它办法来获取该锁。后面我们会说明,在尝试失败的情况下,是如何一步步获取锁的。

 

2. hasQueuedPredecessors()

hasQueuedPredecessors()在AQS中实现,源码如下:

复制代码
public final boolean hasQueuedPredecessors() {    Node t = tail;     Node h = head;    Node s;    return h != t &&        ((s = h.next) == null || s.thread != Thread.currentThread());}
复制代码

说明: 通过代码,能分析出,hasQueuedPredecessors() 是通过判断"当前线程"是不是在CLH队列的队首,来返回AQS中是不是有比“当前线程”等待更久的线程。下面对head、tail和Node进行说明。

 

3. Node的源码

Node就是CLH队列的节点。Node在AQS中实现,它的数据结构如下:

复制代码
private transient volatile Node head;    // CLH队列的队首private transient volatile Node tail;    // CLH队列的队尾// CLH队列的节点static final class Node {    static final Node SHARED = new Node();    static final Node EXCLUSIVE = null;    // 线程已被取消,对应的waitStatus的值    static final int CANCELLED =  1;    // “当前线程的后继线程需要被unpark(唤醒)”,对应的waitStatus的值。    // 一般发生情况是:当前线程的后继线程处于阻塞状态,而当前线程被release或cancel掉,因此需要唤醒当前线程的后继线程。    static final int SIGNAL    = -1;    // 线程(处在Condition休眠状态)在等待Condition唤醒,对应的waitStatus的值    static final int CONDITION = -2;    // (共享锁)其它线程获取到“共享锁”,对应的waitStatus的值    static final int PROPAGATE = -3;    // waitStatus为“CANCELLED, SIGNAL, CONDITION, PROPAGATE”时分别表示不同状态,    // 若waitStatus=0,则意味着当前线程不属于上面的任何一种状态。    volatile int waitStatus;    // 前一节点    volatile Node prev;    // 后一节点    volatile Node next;    // 节点所对应的线程    volatile Thread thread;    // nextWaiter是“区别当前CLH队列是 ‘独占锁’队列 还是 ‘共享锁’队列 的标记”    // 若nextWaiter=SHARED,则CLH队列是“独占锁”队列;    // 若nextWaiter=EXCLUSIVE,(即nextWaiter=null),则CLH队列是“共享锁”队列。    Node nextWaiter;    // “共享锁”则返回true,“独占锁”则返回false。    final boolean isShared() {        return nextWaiter == SHARED;    }    // 返回前一节点    final Node predecessor() throws NullPointerException {        Node p = prev;        if (p == null)            throw new NullPointerException();        else            return p;    }    Node() {    // Used to establish initial head or SHARED marker    }    // 构造函数。thread是节点所对应的线程,mode是用来表示thread的锁是“独占锁”还是“共享锁”。    Node(Thread thread, Node mode) {     // Used by addWaiter        this.nextWaiter = mode;        this.thread = thread;    }    // 构造函数。thread是节点所对应的线程,waitStatus是线程的等待状态。    Node(Thread thread, int waitStatus) { // Used by Condition        this.waitStatus = waitStatus;        this.thread = thread;    }}
复制代码

说明
Node是CLH队列的节点,代表“等待锁的线程队列”。
(01) 每个Node都会一个线程对应。
(02) 每个Node会通过prev和next分别指向上一个节点和下一个节点,这分别代表上一个等待线程和下一个等待线程。
(03) Node通过waitStatus保存线程的等待状态。
(04) Node通过nextWaiter来区分线程是“独占锁”线程还是“共享锁”线程。如果是“独占锁”线程,则nextWaiter的值为EXCLUSIVE;如果是“共享锁”线程,则nextWaiter的值是SHARED。

 

4. compareAndSetState()

compareAndSetState()在AQS中实现。它的源码如下:

protected final boolean compareAndSetState(int expect, int update) {    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);}

说明: compareAndSwapInt() 是sun.misc.Unsafe类中的一个本地方法。对此,我们需要了解的是 compareAndSetState(expect, update) 是以原子的方式操作当前线程;若当前线程的状态为expect,则设置它的状态为update。

 

5. setExclusiveOwnerThread()

setExclusiveOwnerThread()在AbstractOwnableSynchronizer.java中实现,它的源码如下:

// exclusiveOwnerThread是当前拥有“独占锁”的线程private transient Thread exclusiveOwnerThread;protected final void setExclusiveOwnerThread(Thread t) {    exclusiveOwnerThread = t;}

说明:setExclusiveOwnerThread()的作用就是,设置线程t为当前拥有“独占锁”的线程。

 

6. getState(), setState()

getState()和setState()都在AQS中实现,源码如下:

复制代码
// 锁的状态private volatile int state;// 设置锁的状态protected final void setState(int newState) {    state = newState;}// 获取锁的状态protected final int getState() {    return state;}
复制代码

说明:state表示锁的状态,对于“独占锁”而已,state=0表示锁是可获取状态(即,锁没有被任何线程锁持有)。由于java中的独占锁是可重入的,state的值可以>1。

 

小结tryAcquire()的作用就是让“当前线程”尝试获取锁。获取成功返回true,失败则返回false。

 

二. addWaiter(Node.EXCLUSIVE)

addWaiter(Node.EXCLUSIVE)的作用是,创建“当前线程”的Node节点,且Node中记录“当前线程”对应的锁是“独占锁”类型,并且将该节点添加到CLH队列的末尾。

1.addWaiter()

addWaiter()在AQS中实现,源码如下:

复制代码
private Node addWaiter(Node mode) {    // 新建一个Node节点,节点对应的线程是“当前线程”,“当前线程”的锁的模型是mode。    Node node = new Node(Thread.currentThread(), mode);    Node pred = tail;    // 若CLH队列不为空,则将“当前线程”添加到CLH队列末尾    if (pred != null) {        node.prev = pred;        if (compareAndSetTail(pred, node)) {            pred.next = node;            return node;        }    }    // 若CLH队列为空,则调用enq()新建CLH队列,然后再将“当前线程”添加到CLH队列中。    enq(node);    return node;}
复制代码

说明对于“公平锁”而言,addWaiter(Node.EXCLUSIVE)会首先创建一个Node节点,节点的类型是“独占锁”(Node.EXCLUSIVE)类型。然后,再将该节点添加到CLH队列的末尾。

 

2. compareAndSetTail()

compareAndSetTail()在AQS中实现,源码如下:

private final boolean compareAndSetTail(Node expect, Node update) {    return unsafe.compareAndSwapObject(this, tailOffset, expect, update);}

说明compareAndSetTail也属于CAS函数,也是通过“本地方法”实现的。compareAndSetTail(expect, update)会以原子的方式进行操作,它的作用是判断CLH队列的队尾是不是为expect,是的话,就将队尾设为update。

 

3. enq()

enq()在AQS中实现,源码如下:

复制代码
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;            }        }    }}
复制代码

说明: enq()的作用很简单。如果CLH队列为空,则新建一个CLH表头;然后将node添加到CLH末尾。否则,直接将node添加到CLH末尾。

 

小结:addWaiter()的作用,就是将当前线程添加到CLH队列中。这就意味着将当前线程添加到等待获取“锁”的等待线程队列中了。

 

三. acquireQueued()

前面,我们已经将当前线程添加到CLH队列中了。而acquireQueued()的作用就是逐步的去执行CLH队列的线程,如果当前线程获取到了锁,则返回;否则,当前线程进行休眠,直到唤醒并重新获取锁了才返回。下面,我们看看acquireQueued()的具体流程。

 

1. acquireQueued()

acquireQueued()在AQS中实现,源码如下:

复制代码
final boolean acquireQueued(final Node node, int arg) {    boolean failed = true;    try {        // interrupted表示在CLH队列的调度中,        // “当前线程”在休眠时,有没有被中断过。        boolean interrupted = false;        for (;;) {            // 获取上一个节点。            // node是“当前线程”对应的节点,这里就意味着“获取上一个等待锁的线程”。            final Node p = node.predecessor();            if (p == head && tryAcquire(arg)) {                setHead(node);                p.next = null; // help GC                failed = false;                return interrupted;            }            if (shouldParkAfterFailedAcquire(p, node) &&                parkAndCheckInterrupt())                interrupted = true;        }    } finally {        if (failed)            cancelAcquire(node);    }}
复制代码

说明:acquireQueued()的目的是从队列中获取锁。

 

2. shouldParkAfterFailedAcquire()

shouldParkAfterFailedAcquire()在AQS中实现,源码如下:

复制代码
// 返回“当前线程是否应该阻塞”private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {    // 前继节点的状态    int ws = pred.waitStatus;    // 如果前继节点是SIGNAL状态,则意味这当前线程需要被unpark唤醒。此时,返回true。    if (ws == Node.SIGNAL)        return true;    // 如果前继节点是“取消”状态,则设置 “当前节点”的 “当前前继节点”  为  “‘原前继节点’的前继节点”。    if (ws > 0) {        do {            node.prev = pred = pred.prev;        } while (pred.waitStatus > 0);        pred.next = node;    } else {        // 如果前继节点为“0”或者“共享锁”状态,则设置前继节点为SIGNAL状态。        compareAndSetWaitStatus(pred, ws, Node.SIGNAL);    }    return false;}
复制代码

说明
(01) 关于waitStatus请参考下表(中扩号内为waitStatus的值),更多关于waitStatus的内容,可以参考前面的Node类的介绍。

CANCELLED[1]  -- 当前线程已被取消SIGNAL[-1]    -- “当前线程的后继线程需要被unpark(唤醒)”。一般发生情况是:当前线程的后继线程处于阻塞状态,而当前线程被release或cancel掉,因此需要唤醒当前线程的后继线程。CONDITION[-2] -- 当前线程(处在Condition休眠状态)在等待Condition唤醒PROPAGATE[-3] -- (共享锁)其它线程获取到“共享锁”[0]           -- 当前线程不属于上面的任何一种状态。

(02) shouldParkAfterFailedAcquire()通过以下规则,判断“当前线程”是否需要被阻塞。

规则1:如果前继节点状态为SIGNAL,表明当前节点需要被unpark(唤醒),此时则返回true。规则2:如果前继节点状态为CANCELLED(ws>0),说明前继节点已经被取消,则通过先前回溯找到一个有效(非CANCELLED状态)的节点,并返回false。规则3:如果前继节点状态为非SIGNAL、非CANCELLED,则设置前继的状态为SIGNAL,并返回false。

如果“规则1”发生,即“前继节点是SIGNAL”状态,则意味着“当前线程”需要被阻塞。接下来会调用parkAndCheckInterrupt()阻塞当前线程,直到当前先被唤醒才从parkAndCheckInterrupt()中返回。

 

3. parkAndCheckInterrupt())

parkAndCheckInterrupt()在AQS中实现,源码如下:

private final boolean parkAndCheckInterrupt() {    // 通过LockSupport的park()阻塞“当前线程”。    LockSupport.park(this);    // 返回线程的中断状态。    return Thread.interrupted();}

说明parkAndCheckInterrupt()的作用是阻塞当前线程,并且返回“线程被唤醒之后”的中断状态。
它会先通过LockSupport.park()阻塞“当前线程”,然后通过Thread.interrupted()返回线程的中断状态。

这里介绍一下线程被阻塞之后如何唤醒。一般有2种情况:
第1种情况:unpark()唤醒。“前继节点对应的线程”使用完锁之后,通过unpark()方式唤醒当前线程。
第2种情况:中断唤醒。其它线程通过interrupt()中断当前线程。

补充:LockSupport()中的park(),unpark()的作用 和 Object中的wait(),notify()作用类似,是阻塞/唤醒。
它们的用法不同,park(),unpark()是轻量级的,而wait(),notify()是必须先通过Synchronized获取同步锁。
关于LockSupport,我们会在之后的章节再专门进行介绍!

 

4. 再次tryAcquire()

了解了shouldParkAfterFailedAcquire()和parkAndCheckInterrupt()函数之后。我们接着分析acquireQueued()的for循环部分。

复制代码
final Node p = node.predecessor();if (p == head && tryAcquire(arg)) {    setHead(node);    p.next = null; // help GC    failed = false;    return interrupted;}
复制代码

说明
(01) 通过node.predecessor()获取前继节点。predecessor()就是返回node的前继节点,若对此有疑惑可以查看下面关于Node类的介绍。
(02) p == head && tryAcquire(arg)
       首先,判断“前继节点”是不是CHL表头。如果是的话,则通过tryAcquire()尝试获取锁。
       其实,这样做的目的是为了“让当前线程获取锁”,但是为什么需要先判断p==head呢?理解这个对理解“公平锁”的机制很重要,因为这么做的原因就是为了保证公平性!
       (a) 前面,我们在shouldParkAfterFailedAcquire()我们判断“当前线程”是否需要阻塞;
       (b) 接着,“当前线程”阻塞的话,会调用parkAndCheckInterrupt()来阻塞线程。当线程被解除阻塞的时候,我们会返回线程的中断状态。而线程被解决阻塞,可能是由于“线程被中断”,也可能是由于“其它线程调用了该线程的unpark()函数”。
       (c) 再回到p==head这里。如果当前线程是因为其它线程调用了unpark()函数而被唤醒,那么唤醒它的线程,应该是它的前继节点所对应的线程(关于这一点,后面在“释放锁”的过程中会看到)。 OK,是前继节点调用unpark()唤醒了当前线程!
            此时,再来理解p==head就很简单了:当前继节点是CLH队列的头节点,并且它释放锁之后;就轮到当前节点获取锁了。然后,当前节点通过tryAcquire()获取锁;获取成功的话,通过setHead(node)设置当前节点为头节点,并返回。
       总之,如果“前继节点调用unpark()唤醒了当前线程”并且“前继节点是CLH表头”,此时就是满足p==head,也就是符合公平性原则的。否则,如果当前线程是因为“线程被中断”而唤醒,那么显然就不是公平了。这就是为什么说p==head就是保证公平性!


小结acquireQueued()的作用就是“当前线程”会根据公平性原则进行阻塞等待,直到获取锁为止;并且返回当前线程在等待过程中有没有并中断过。

 

四. selfInterrupt()

selfInterrupt()是AQS中实现,源码如下:

private static void selfInterrupt() {    Thread.currentThread().interrupt();}

说明selfInterrupt()的代码很简单,就是“当前线程”自己产生一个中断。但是,为什么需要这么做呢?
这必须结合acquireQueued()进行分析。如果在acquireQueued()中,当前线程被中断过,则执行selfInterrupt();否则不会执行。

在acquireQueued()中,即使是线程在阻塞状态被中断唤醒而获取到cpu执行权利;但是,如果该线程的前面还有其它等待锁的线程,根据公平性原则,该线程依然无法获取到锁。它会再次阻塞! 该线程再次阻塞,直到该线程被它的前面等待锁的线程锁唤醒;线程才会获取锁,然后“真正执行起来”!
也就是说,在该线程“成功获取锁并真正执行起来”之前,它的中断会被忽略并且中断标记会被清除! 因为在parkAndCheckInterrupt()中,我们线程的中断状态时调用了Thread.interrupted()。该函数不同于Thread的isInterrupted()函数,isInterrupted()仅仅返回中断状态,而interrupted()在返回当前中断状态之后,还会清除中断状态。 正因为之前的中断状态被清除了,所以这里需要调用selfInterrupt()重新产生一个中断!

 

小结selfInterrupt()的作用就是当前线程自己产生一个中断。

 

总结

再回过头看看acquire()函数,它最终的目的是获取锁!

public final void acquire(int arg) {    if (!tryAcquire(arg) &&        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))        selfInterrupt();}

(01) 先是通过tryAcquire()尝试获取锁。获取成功的话,直接返回;尝试失败的话,再通过acquireQueued()获取锁。
(02) 尝试失败的情况下,会先通过addWaiter()来将“当前线程”加入到"CLH队列"末尾;然后调用acquireQueued(),在CLH队列中排序等待获取锁,在此过程中,线程处于休眠状态。直到获取锁了才返回。 如果在休眠等待过程中被中断过,则调用selfInterrupt()来自己产生一个中断。

 

0 0
原创粉丝点击