• AQS应用之Lock
    Java并发编程核心在于java.concurrent.util包而juc当中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队列、独占获取、共享获取等,而这个行为的抽象就是基于AbstractQueuedSynchronizer简称AQS,AQS定义了一套多线程访问共享资源的同步器框架,是一个依赖状态(state)的同步器。
  • ReentrantLock
    ReentrantLock是一种基于AQS框架的应用实现,是JDK中的一种线程并发访问的同步手段,它的功能类似于synchronized是一种互斥锁,可以保证线程安全。而且它具有比synchronized更多的特性,比如它支持手动加锁与解锁,支持加锁的公平性
package com.zgs;import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockTest {public static void main(String[] args) {//使用ReentrantLock进行同步ReentrantLock lock = new ReentrantLock(false);//false为非公平锁,true为公平锁try {} catch (Exception e) {} finally {lock.unlock(); //解锁}}
}

ReentrantLock如何实现synchronized不具备的公平与非公平性呢?
在ReentrantLock内部定义了一个Sync的内部类,该类继承AbstractQueuedSynchronized,对该抽象类的部分方法做了实现;并且还定义了两个子类:
1、FairSync 公平锁的实现
2、NonfairSync 非公平锁的实现
这两个类都继承自Sync,也就是间接继承了AbstractQueuedSynchronized,所以这一个ReentrantLock同时具备公平与非公平特性。上面主要涉及的设计模式:模板模式-子类根据需要做具体业务实现。

AQS具备特性
阻塞等待队列
共享/独占
公平/非公平
可重入
允许中断

除了Lock外,Java.concurrent.util当中同步器的实现如Latch,Barrier,BlockingQueue等,都是基于AQS框架实现。
一般通过定义内部类Sync继承AQS
将同步器所有调用都映射到Sync对应的方法

AQS内部维护属性volatile int state (32位)
state表示资源的可用状态

State三种访问方式
getState()、setState()、compareAndSetState()

AQS定义两种资源共享方式
Exclusive-独占,只有一个线程能执行,如ReentrantLock
Share-共享,多个线程可以同时执行,如Semaphore/CountDownLatch

AQS定义两种队列
同步等待队列
条件等待队列

不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。

自定义同步器实现时主要实现以下几种方法:

  • isHeldExclusively():

该线程是否正在独占资源。只有用到condition才需要去实现它。

  • tryAcquire(int):

独占方式。尝试获取资源,成功则返回true,失败则返回false。

  • tryRelease(int):

独占方式。尝试释放资源,成功则返回true,失败则返回false。

  • tryAcquireShared(int):

共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。

  • tryReleaseShared(int):

共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。

同步等待队列
AQS当中的同步等待队列也称CLH队列,CLH队列是Craig、Landin、Hagersten三人发明的一种基于双向链表数据结构的队列,是FIFO先入先出线程等待队列,Java中的CLH队列是原CLH队列的一个变种,线程由原自旋机制改为阻塞机制。

条件等待队列
Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备时,这些等待线程才会被唤醒,从而重新争夺锁。

LockSupport功能代码示例:

package com.yg.edu.lock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.locks.LockSupport;/*** @author :杨过* @date :Created in 2020/4/28* @version: V1.0* @slogan: 天下风云出我辈,一入代码岁月催* @description:**/
@Slf4j
public class Juc01_Thread_LockSupport {public static void main(String[] args) {Thread t0 = new Thread(new Runnable() {@Overridepublic void run() {Thread current = Thread.currentThread();System.out.println(current.getName() + "开始执行!");for (; ; ) {//spin 自旋System.out.println(current.getName() + "准备park住当前线程");LockSupport.park();System.out.println(current.getName() + "当前线程{}已经被唤醒");}}}, "t0");t0.start();try {Thread.sleep(5000);System.out.println(t0.getName() + "准备唤醒{}线程!");LockSupport.unpark(t0);} catch (InterruptedException e) {e.printStackTrace();}}
}

CAS功能代码示例

package com.yg.edu.lock;import com.yg.edu.util.UnsafeInstance;
import lombok.extern.slf4j.Slf4j;
import sun.misc.Unsafe;import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;/*** ,;,,;* ,;;'(    社* __      ,;;' ' \   会* /'  '\'~~'~' \ /'\.)  主* ,;(      )    /  |.     义* ,;' \    /-.,,(   ) \    码* ) /       ) / )|    农* ||        ||  \)* (_\       (_\** @author :杨过* @date :Created in 2020/5/13 14:42* @version: V1.0* @slogan: 天下风云出我辈,一入代码岁月催* @description:**/
@Slf4j
public class Juc04_Thread_Cas {/*** 当前加锁状态,记录加锁的次数*/private volatile int state = 0;private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5);private static Juc04_Thread_Cas cas = new Juc04_Thread_Cas();public static void main(String[] args) {new Thread(new Worker(), "t-0").start();new Thread(new Worker(), "t-1").start();new Thread(new Worker(), "t-2").start();new Thread(new Worker(), "t-3").start();new Thread(new Worker(), "t-4").start();}static class Worker implements Runnable {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + "请求:到达预定点,准备开始抢state:)");try {cyclicBarrier.await();if (cas.compareAndSwapState(0, 1)) {System.out.println(Thread.currentThread().getName() + "请求:,抢到锁!");} else {System.out.println(Thread.currentThread().getName() + "请求:,抢锁失败!");}} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}}}/*** 原子操作** @param oldValue        oldvalue:线程工作内存当中的值* @param newValue:要替换的新值* @return*/public final boolean compareAndSwapState(int oldValue, int newValue) {return unsafe.compareAndSwapInt(this, stateOffset, oldValue, newValue);}private static final Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();private static final long stateOffset;static {try {stateOffset = unsafe.objectFieldOffset(Juc04_Thread_Cas.class.getDeclaredField("state"));} catch (Exception e) {throw new Error();}}
}

AQS源码分析

/** ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************//******* Written by Doug Lea with assistance from members of JCP JSR-166* Expert Group and released to the public domain, as explained at* http://creativecommons.org/publicdomain/zero/1.0/*/package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import sun.misc.Unsafe;/*** Provides a framework for implementing blocking locks and related* synchronizers (semaphores, events, etc) that rely on* first-in-first-out (FIFO) wait queues.  This class is designed to* be a useful basis for most kinds of synchronizers that rely on a* single atomic {@code int} value to represent state. Subclasses* must define the protected methods that change this state, and which* define what that state means in terms of this object being acquired* or released.  Given these, the other methods in this class carry* out all queuing and blocking mechanics. Subclasses can maintain* other state fields, but only the atomically updated {@code int}* value manipulated using methods {@link #getState}, {@link* #setState} and {@link #compareAndSetState} is tracked with respect* to synchronization.** <p>Subclasses should be defined as non-public internal helper* classes that are used to implement the synchronization properties* of their enclosing class.  Class* {@code AbstractQueuedSynchronizer} does not implement any* synchronization interface.  Instead it defines methods such as* {@link #acquireInterruptibly} that can be invoked as* appropriate by concrete locks and related synchronizers to* implement their public methods.** <p>This class supports either or both a default <em>exclusive</em>* mode and a <em>shared</em> mode. When acquired in exclusive mode,* attempted acquires by other threads cannot succeed. Shared mode* acquires by multiple threads may (but need not) succeed. This class* does not &quot;understand&quot; these differences except in the* mechanical sense that when a shared mode acquire succeeds, the next* waiting thread (if one exists) must also determine whether it can* acquire as well. Threads waiting in the different modes share the* same FIFO queue. Usually, implementation subclasses support only* one of these modes, but both can come into play for example in a* {@link ReadWriteLock}. Subclasses that support only exclusive or* only shared modes need not define the methods supporting the unused mode.** <p>This class defines a nested {@link ConditionObject} class that* can be used as a {@link Condition} implementation by subclasses* supporting exclusive mode for which method {@link* #isHeldExclusively} reports whether synchronization is exclusively* held with respect to the current thread, method {@link #release}* invoked with the current {@link #getState} value fully releases* this object, and {@link #acquire}, given this saved state value,* eventually restores this object to its previous acquired state.  No* {@code AbstractQueuedSynchronizer} method otherwise creates such a* condition, so if this constraint cannot be met, do not use it.  The* behavior of {@link ConditionObject} depends of course on the* semantics of its synchronizer implementation.** <p>This class provides inspection, instrumentation, and monitoring* methods for the internal queue, as well as similar methods for* condition objects. These can be exported as desired into classes* using an {@code AbstractQueuedSynchronizer} for their* synchronization mechanics.** <p>Serialization of this class stores only the underlying atomic* integer maintaining state, so deserialized objects have empty* thread queues. Typical subclasses requiring serializability will* define a {@code readObject} method that restores this to a known* initial state upon deserialization.** <h3>Usage</h3>** <p>To use this class as the basis of a synchronizer, redefine the* following methods, as applicable, by inspecting and/or modifying* the synchronization state using {@link #getState}, {@link* #setState} and/or {@link #compareAndSetState}:** <ul>* <li> {@link #tryAcquire}* <li> {@link #tryRelease}* <li> {@link #tryAcquireShared}* <li> {@link #tryReleaseShared}* <li> {@link #isHeldExclusively}* </ul>** Each of these methods by default throws {@link* UnsupportedOperationException}.  Implementations of these methods* must be internally thread-safe, and should in general be short and* not block. Defining these methods is the <em>only</em> supported* means of using this class. All other methods are declared* {@code final} because they cannot be independently varied.** <p>You may also find the inherited methods from {@link* AbstractOwnableSynchronizer} useful to keep track of the thread* owning an exclusive synchronizer.  You are encouraged to use them* -- this enables monitoring and diagnostic tools to assist users in* determining which threads hold locks.** <p>Even though this class is based on an internal FIFO queue, it* does not automatically enforce FIFO acquisition policies.  The core* of exclusive synchronization takes the form:** <pre>* Acquire:*     while (!tryAcquire(arg)) {*        <em>enqueue thread if it is not already queued</em>;*        <em>possibly block current thread</em>;*     }** Release:*     if (tryRelease(arg))*        <em>unblock the first queued thread</em>;* </pre>** (Shared mode is similar but may involve cascading signals.)** <p id="barging">Because checks in acquire are invoked before* enqueuing, a newly acquiring thread may <em>barge</em> ahead of* others that are blocked and queued.  However, you can, if desired,* define {@code tryAcquire} and/or {@code tryAcquireShared} to* disable barging by internally invoking one or more of the inspection* methods, thereby providing a <em>fair</em> FIFO acquisition order.* In particular, most fair synchronizers can define {@code tryAcquire}* to return {@code false} if {@link #hasQueuedPredecessors} (a method* specifically designed to be used by fair synchronizers) returns* {@code true}.  Other variations are possible.** <p>Throughput and scalability are generally highest for the* default barging (also known as <em>greedy</em>,* <em>renouncement</em>, and <em>convoy-avoidance</em>) strategy.* While this is not guaranteed to be fair or starvation-free, earlier* queued threads are allowed to recontend before later queued* threads, and each recontention has an unbiased chance to succeed* against incoming threads.  Also, while acquires do not* &quot;spin&quot; in the usual sense, they may perform multiple* invocations of {@code tryAcquire} interspersed with other* computations before blocking.  This gives most of the benefits of* spins when exclusive synchronization is only briefly held, without* most of the liabilities when it isn't. If so desired, you can* augment this by preceding calls to acquire methods with* "fast-path" checks, possibly prechecking {@link #hasContended}* and/or {@link #hasQueuedThreads} to only do so if the synchronizer* is likely not to be contended.** <p>This class provides an efficient and scalable basis for* synchronization in part by specializing its range of use to* synchronizers that can rely on {@code int} state, acquire, and* release parameters, and an internal FIFO wait queue. When this does* not suffice, you can build synchronizers from a lower level using* {@link java.util.concurrent.atomic atomic} classes, your own custom* {@link java.util.Queue} classes, and {@link LockSupport} blocking* support.** <h3>Usage Examples</h3>** <p>Here is a non-reentrant mutual exclusion lock class that uses* the value zero to represent the unlocked state, and one to* represent the locked state. While a non-reentrant lock* does not strictly require recording of the current owner* thread, this class does so anyway to make usage easier to monitor.* It also supports conditions and exposes* one of the instrumentation methods:**  <pre> {@code* class Mutex implements Lock, java.io.Serializable {**   // Our internal helper class*   private static class Sync extends AbstractQueuedSynchronizer {*     // Reports whether in locked state*     protected boolean isHeldExclusively() {*       return getState() == 1;*     }**     // Acquires the lock if state is zero*     public boolean tryAcquire(int acquires) {*       assert acquires == 1; // Otherwise unused*       if (compareAndSetState(0, 1)) {*         setExclusiveOwnerThread(Thread.currentThread());*         return true;*       }*       return false;*     }**     // Releases the lock by setting state to zero*     protected boolean tryRelease(int releases) {*       assert releases == 1; // Otherwise unused*       if (getState() == 0) throw new IllegalMonitorStateException();*       setExclusiveOwnerThread(null);*       setState(0);*       return true;*     }**     // Provides a Condition*     Condition newCondition() { return new ConditionObject(); }**     // Deserializes properly*     private void readObject(ObjectInputStream s)*         throws IOException, ClassNotFoundException {*       s.defaultReadObject();*       setState(0); // reset to unlocked state*     }*   }**   // The sync object does all the hard work. We just forward to it.*   private final Sync sync = new Sync();**   public void lock()                { sync.acquire(1); }*   public boolean tryLock()          { return sync.tryAcquire(1); }*   public void unlock()              { sync.release(1); }*   public Condition newCondition()   { return sync.newCondition(); }*   public boolean isLocked()         { return sync.isHeldExclusively(); }*   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }*   public void lockInterruptibly() throws InterruptedException {*     sync.acquireInterruptibly(1);*   }*   public boolean tryLock(long timeout, TimeUnit unit)*       throws InterruptedException {*     return sync.tryAcquireNanos(1, unit.toNanos(timeout));*   }* }}</pre>** <p>Here is a latch class that is like a* {@link java.util.concurrent.CountDownLatch CountDownLatch}* except that it only requires a single {@code signal} to* fire. Because a latch is non-exclusive, it uses the {@code shared}* acquire and release methods.**  <pre> {@code* class BooleanLatch {**   private static class Sync extends AbstractQueuedSynchronizer {*     boolean isSignalled() { return getState() != 0; }**     protected int tryAcquireShared(int ignore) {*       return isSignalled() ? 1 : -1;*     }**     protected boolean tryReleaseShared(int ignore) {*       setState(1);*       return true;*     }*   }**   private final Sync sync = new Sync();*   public boolean isSignalled() { return sync.isSignalled(); }*   public void signal()         { sync.releaseShared(1); }*   public void await() throws InterruptedException {*     sync.acquireSharedInterruptibly(1);*   }* }}</pre>** @since 1.5* @author Doug Lea*/
public abstract class AbstractQueuedSynchronizerextends AbstractOwnableSynchronizerimplements java.io.Serializable {private static final long serialVersionUID = 7373984972572414691L;/*** Creates a new {@code AbstractQueuedSynchronizer} instance* with initial synchronization state of zero.*/protected AbstractQueuedSynchronizer() { }/*** Wait queue node class.** <p>The wait queue is a variant of a "CLH" (Craig, Landin, and* Hagersten) lock queue. CLH locks are normally used for* spinlocks.  We instead use them for blocking synchronizers, but* use the same basic tactic of holding some of the control* information about a thread in the predecessor of its node.  A* "status" field in each node keeps track of whether a thread* should block.  A node is signalled when its predecessor* releases.  Each node of the queue otherwise serves as a* specific-notification-style monitor holding a single waiting* thread. The status field does NOT control whether threads are* granted locks etc though.  A thread may try to acquire if it is* first in the queue. But being first does not guarantee success;* it only gives the right to contend.  So the currently released* contender thread may need to rewait.** <p>To enqueue into a CLH lock, you atomically splice it in as new* tail. To dequeue, you just set the head field.* <pre>*      +------+  prev +-----+       +-----+* head |      | <---- |     | <---- |     |  tail*      +------+       +-----+       +-----+* </pre>** <p>Insertion into a CLH queue requires only a single atomic* operation on "tail", so there is a simple atomic point of* demarcation from unqueued to queued. Similarly, dequeuing* involves only updating the "head". However, it takes a bit* more work for nodes to determine who their successors are,* in part to deal with possible cancellation due to timeouts* and interrupts.** <p>The "prev" links (not used in original CLH locks), are mainly* needed to handle cancellation. If a node is cancelled, its* successor is (normally) relinked to a non-cancelled* predecessor. For explanation of similar mechanics in the case* of spin locks, see the papers by Scott and Scherer at* http://www.cs.rochester.edu/u/scott/synchronization/** <p>We also use "next" links to implement blocking mechanics.* The thread id for each node is kept in its own node, so a* predecessor signals the next node to wake up by traversing* next link to determine which thread it is.  Determination of* successor must avoid races with newly queued nodes to set* the "next" fields of their predecessors.  This is solved* when necessary by checking backwards from the atomically* updated "tail" when a node's successor appears to be null.* (Or, said differently, the next-links are an optimization* so that we don't usually need a backward scan.)** <p>Cancellation introduces some conservatism to the basic* algorithms.  Since we must poll for cancellation of other* nodes, we can miss noticing whether a cancelled node is* ahead or behind us. This is dealt with by always unparking* successors upon cancellation, allowing them to stabilize on* a new predecessor, unless we can identify an uncancelled* predecessor who will carry this responsibility.** <p>CLH queues need a dummy header node to get started. But* we don't create them on construction, because it would be wasted* effort if there is never contention. Instead, the node* is constructed and head and tail pointers are set upon first* contention.** <p>Threads waiting on Conditions use the same nodes, but* use an additional link. Conditions only need to link nodes* in simple (non-concurrent) linked queues because they are* only accessed when exclusively held.  Upon await, a node is* inserted into a condition queue.  Upon signal, the node is* transferred to the main queue.  A special value of status* field is used to mark which queue a node is on.** <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill* Scherer and Michael Scott, along with members of JSR-166* expert group, for helpful ideas, discussions, and critiques* on the design of this class.*/static final class Node {/** Marker to indicate a node is waiting in shared mode */static final Node SHARED = new Node();/** Marker to indicate a node is waiting in exclusive mode */static final Node EXCLUSIVE = null;/** waitStatus value to indicate thread has cancelled */static final int CANCELLED =  1;/** waitStatus value to indicate successor's thread needs unparking */static final int SIGNAL    = -1;/** waitStatus value to indicate thread is waiting on condition */static final int CONDITION = -2;/*** waitStatus value to indicate the next acquireShared should* unconditionally propagate*/static final int PROPAGATE = -3;/*** Status field, taking on only the values:*   SIGNAL:     The successor of this node is (or will soon be)*               blocked (via park), so the current node must*               unpark its successor when it releases or*               cancels. To avoid races, acquire methods must*               first indicate they need a signal,*               then retry the atomic acquire, and then,*               on failure, block.*   CANCELLED:  This node is cancelled due to timeout or interrupt.*               Nodes never leave this state. In particular,*               a thread with cancelled node never again blocks.*   CONDITION:  This node is currently on a condition queue.*               It will not be used as a sync queue node*               until transferred, at which time the status*               will be set to 0. (Use of this value here has*               nothing to do with the other uses of the*               field, but simplifies mechanics.)*   PROPAGATE:  A releaseShared should be propagated to other*               nodes. This is set (for head node only) in*               doReleaseShared to ensure propagation*               continues, even if other operations have*               since intervened.*   0:          None of the above** The values are arranged numerically to simplify use.* Non-negative values mean that a node doesn't need to* signal. So, most code doesn't need to check for particular* values, just for sign.** The field is initialized to 0 for normal sync nodes, and* CONDITION for condition nodes.  It is modified using CAS* (or when possible, unconditional volatile writes).*/volatile int waitStatus;/*** Link to predecessor node that current node/thread relies on* for checking waitStatus. Assigned during enqueuing, and nulled* out (for sake of GC) only upon dequeuing.  Also, upon* cancellation of a predecessor, we short-circuit while* finding a non-cancelled one, which will always exist* because the head node is never cancelled: A node becomes* head only as a result of successful acquire. A* cancelled thread never succeeds in acquiring, and a thread only* cancels itself, not any other node.*/volatile Node prev;/*** Link to the successor node that the current node/thread* unparks upon release. Assigned during enqueuing, adjusted* when bypassing cancelled predecessors, and nulled out (for* sake of GC) when dequeued.  The enq operation does not* assign next field of a predecessor until after attachment,* so seeing a null next field does not necessarily mean that* node is at end of queue. However, if a next field appears* to be null, we can scan prev's from the tail to* double-check.  The next field of cancelled nodes is set to* point to the node itself instead of null, to make life* easier for isOnSyncQueue.*/volatile Node next;/*** The thread that enqueued this node.  Initialized on* construction and nulled out after use.*/volatile Thread thread;/*** Link to next node waiting on condition, or the special* value SHARED.  Because condition queues are accessed only* when holding in exclusive mode, we just need a simple* linked queue to hold nodes while they are waiting on* conditions. They are then transferred to the queue to* re-acquire. And because conditions can only be exclusive,* we save a field by using special value to indicate shared* mode.*/Node nextWaiter;/*** Returns true if node is waiting in shared mode.*/final boolean isShared() {return nextWaiter == SHARED;}/*** Returns previous node, or throws NullPointerException if null.* Use when predecessor cannot be null.  The null check could* be elided, but is present to help the VM.** @return the predecessor of this node*/final Node predecessor() throws NullPointerException {Node p = prev;if (p == null)throw new NullPointerException();elsereturn p;}Node() {    // Used to establish initial head or SHARED marker}Node(Thread thread, Node mode) {     // Used by addWaiterthis.nextWaiter = mode;this.thread = thread;}Node(Thread thread, int waitStatus) { // Used by Conditionthis.waitStatus = waitStatus;this.thread = thread;}}/*** Head of the wait queue, lazily initialized.  Except for* initialization, it is modified only via method setHead.  Note:* If head exists, its waitStatus is guaranteed not to be* CANCELLED.*/private transient volatile Node head;/*** Tail of the wait queue, lazily initialized.  Modified only via* method enq to add new wait node.*/private transient volatile Node tail;/*** The synchronization state.*/private volatile int state;/*** Returns the current value of synchronization state.* This operation has memory semantics of a {@code volatile} read.* @return current state value*/protected final int getState() {return state;}/*** Sets the value of synchronization state.* This operation has memory semantics of a {@code volatile} write.* @param newState the new state value*/protected final void setState(int newState) {state = newState;}/*** Atomically sets synchronization state to the given updated* value if the current state value equals the expected value.* This operation has memory semantics of a {@code volatile} read* and write.** @param expect the expected value* @param update the new value* @return {@code true} if successful. False return indicates that the actual*         value was not equal to the expected value.*/protected final boolean compareAndSetState(int expect, int update) {// See below for intrinsics setup to support thisreturn unsafe.compareAndSwapInt(this, stateOffset, expect, update);}// Queuing utilities/*** The number of nanoseconds for which it is faster to spin* rather than to use timed park. A rough estimate suffices* to improve responsiveness with very short timeouts.*/static final long spinForTimeoutThreshold = 1000L;/*** Inserts node into queue, initializing if necessary. See picture above.* @param node the node to insert* @return node's predecessor*/private Node enq(final Node node) {for (;;) {Node t = tail;if (t == null) { // Must initializeif (compareAndSetHead(new Node()))tail = head;} else {node.prev = t;if (compareAndSetTail(t, node)) {t.next = node;return t;}}}}/*** Creates and enqueues node for current thread and given mode.** @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared* @return the new node*/private Node addWaiter(Node mode) {Node node = new Node(Thread.currentThread(), mode);// Try the fast path of enq; backup to full enq on failureNode pred = tail;if (pred != null) {node.prev = pred;if (compareAndSetTail(pred, node)) {pred.next = node;return node;}}enq(node);return node;}/*** Sets head of queue to be node, thus dequeuing. Called only by* acquire methods.  Also nulls out unused fields for sake of GC* and to suppress unnecessary signals and traversals.** @param node the node*/private void setHead(Node node) {head = node;node.thread = null;node.prev = null;}/*** Wakes up node's successor, if one exists.** @param node the node*/private void unparkSuccessor(Node node) {/** If status is negative (i.e., possibly needing signal) try* to clear in anticipation of signalling.  It is OK if this* fails or if status is changed by waiting thread.*/int ws = node.waitStatus;if (ws < 0)compareAndSetWaitStatus(node, ws, 0);/** Thread to unpark is held in successor, which is normally* just the next node.  But if cancelled or apparently null,* traverse backwards from tail to find the actual* non-cancelled successor.*/Node s = node.next;if (s == null || s.waitStatus > 0) {s = null;for (Node t = tail; t != null && t != node; t = t.prev)if (t.waitStatus <= 0)s = t;}if (s != null)LockSupport.unpark(s.thread);}/*** Release action for shared mode -- signals successor and ensures* propagation. (Note: For exclusive mode, release just amounts* to calling unparkSuccessor of head if it needs signal.)*/private void doReleaseShared() {/** Ensure that a release propagates, even if there are other* in-progress acquires/releases.  This proceeds in the usual* way of trying to unparkSuccessor of head if it needs* signal. But if it does not, status is set to PROPAGATE to* ensure that upon release, propagation continues.* Additionally, we must loop in case a new node is added* while we are doing this. Also, unlike other uses of* unparkSuccessor, we need to know if CAS to reset status* fails, if so rechecking.*/for (;;) {Node h = head;if (h != null && h != tail) {int ws = h.waitStatus;if (ws == Node.SIGNAL) {if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))continue;            // loop to recheck casesunparkSuccessor(h);}else if (ws == 0 &&!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))continue;                // loop on failed CAS}if (h == head)                   // loop if head changedbreak;}}/*** Sets head of queue, and checks if successor may be waiting* in shared mode, if so propagating if either propagate > 0 or* PROPAGATE status was set.** @param node the node* @param propagate the return value from a tryAcquireShared*/private void setHeadAndPropagate(Node node, int propagate) {Node h = head; // Record old head for check belowsetHead(node);/** Try to signal next queued node if:*   Propagation was indicated by caller,*     or was recorded (as h.waitStatus either before*     or after setHead) by a previous operation*     (note: this uses sign-check of waitStatus because*      PROPAGATE status may transition to SIGNAL.)* and*   The next node is waiting in shared mode,*     or we don't know, because it appears null** The conservatism in both of these checks may cause* unnecessary wake-ups, but only when there are multiple* racing acquires/releases, so most need signals now or soon* anyway.*/if (propagate > 0 || h == null || h.waitStatus < 0 ||(h = head) == null || h.waitStatus < 0) {Node s = node.next;if (s == null || s.isShared())doReleaseShared();}}// Utilities for various versions of acquire/*** Cancels an ongoing attempt to acquire.** @param node the node*/private void cancelAcquire(Node node) {// Ignore if node doesn't existif (node == null)return;node.thread = null;// Skip cancelled predecessorsNode pred = node.prev;while (pred.waitStatus > 0)node.prev = pred = pred.prev;// predNext is the apparent node to unsplice. CASes below will// fail if not, in which case, we lost race vs another cancel// or signal, so no further action is necessary.Node predNext = pred.next;// Can use unconditional write instead of CAS here.// After this atomic step, other Nodes can skip past us.// Before, we are free of interference from other threads.node.waitStatus = Node.CANCELLED;// If we are the tail, remove ourselves.if (node == tail && compareAndSetTail(node, pred)) {compareAndSetNext(pred, predNext, null);} else {// If successor needs signal, try to set pred's next-link// so it will get one. Otherwise wake it up to propagate.int ws;if (pred != head &&((ws = pred.waitStatus) == Node.SIGNAL ||(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&pred.thread != null) {Node next = node.next;if (next != null && next.waitStatus <= 0)compareAndSetNext(pred, predNext, next);} else {unparkSuccessor(node);}node.next = node; // help GC}}/*** Checks and updates status for a node that failed to acquire.* Returns true if thread should block. This is the main signal* control in all acquire loops.  Requires that pred == node.prev.** @param pred node's predecessor holding status* @param node the node* @return {@code true} if thread should block*/private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {int ws = pred.waitStatus;if (ws == Node.SIGNAL)/** This node has already set status asking a release* to signal it, so it can safely park.*/return true;if (ws > 0) {/** Predecessor was cancelled. Skip over predecessors and* indicate retry.*/do {node.prev = pred = pred.prev;} while (pred.waitStatus > 0);pred.next = node;} else {/** waitStatus must be 0 or PROPAGATE.  Indicate that we* need a signal, but don't park yet.  Caller will need to* retry to make sure it cannot acquire before parking.*/compareAndSetWaitStatus(pred, ws, Node.SIGNAL);}return false;}/*** Convenience method to interrupt current thread.*/static void selfInterrupt() {Thread.currentThread().interrupt();}/*** Convenience method to park and then check if interrupted** @return {@code true} if interrupted*/private final boolean parkAndCheckInterrupt() {LockSupport.park(this);return Thread.interrupted();}/** Various flavors of acquire, varying in exclusive/shared and* control modes.  Each is mostly the same, but annoyingly* different.  Only a little bit of factoring is possible due to* interactions of exception mechanics (including ensuring that we* cancel if tryAcquire throws exception) and other control, at* least not without hurting performance too much.*//*** Acquires in exclusive uninterruptible mode for thread already in* queue. Used by condition wait methods as well as acquire.** @param node the node* @param arg the acquire argument* @return {@code true} if interrupted while waiting*/final boolean acquireQueued(final Node node, int arg) {boolean failed = true;try {boolean interrupted = false;for (;;) {final Node p = node.predecessor();if (p == head && tryAcquire(arg)) {setHead(node);p.next = null; // help GCfailed = false;return interrupted;}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node);}}/*** Acquires in exclusive interruptible mode.* @param arg the acquire argument*/private void doAcquireInterruptibly(int arg)throws InterruptedException {final Node node = addWaiter(Node.EXCLUSIVE);boolean failed = true;try {for (;;) {final Node p = node.predecessor();if (p == head && tryAcquire(arg)) {setHead(node);p.next = null; // help GCfailed = false;return;}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}}/*** Acquires in exclusive timed mode.** @param arg the acquire argument* @param nanosTimeout max wait time* @return {@code true} if acquired*/private boolean doAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (nanosTimeout <= 0L)return false;final long deadline = System.nanoTime() + nanosTimeout;final Node node = addWaiter(Node.EXCLUSIVE);boolean failed = true;try {for (;;) {final Node p = node.predecessor();if (p == head && tryAcquire(arg)) {setHead(node);p.next = null; // help GCfailed = false;return true;}nanosTimeout = deadline - System.nanoTime();if (nanosTimeout <= 0L)return false;if (shouldParkAfterFailedAcquire(p, node) &&nanosTimeout > spinForTimeoutThreshold)LockSupport.parkNanos(this, nanosTimeout);if (Thread.interrupted())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}}/*** Acquires in shared uninterruptible mode.* @param arg the acquire argument*/private void doAcquireShared(int arg) {final Node node = addWaiter(Node.SHARED);boolean failed = true;try {boolean interrupted = false;for (;;) {final Node p = node.predecessor();if (p == head) {int r = tryAcquireShared(arg);if (r >= 0) {setHeadAndPropagate(node, r);p.next = null; // help GCif (interrupted)selfInterrupt();failed = false;return;}}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node);}}/*** Acquires in shared interruptible mode.* @param arg the acquire argument*/private void doAcquireSharedInterruptibly(int arg)throws InterruptedException {final Node node = addWaiter(Node.SHARED);boolean failed = true;try {for (;;) {final Node p = node.predecessor();if (p == head) {int r = tryAcquireShared(arg);if (r >= 0) {setHeadAndPropagate(node, r);p.next = null; // help GCfailed = false;return;}}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}}/*** Acquires in shared timed mode.** @param arg the acquire argument* @param nanosTimeout max wait time* @return {@code true} if acquired*/private boolean doAcquireSharedNanos(int arg, long nanosTimeout)throws InterruptedException {if (nanosTimeout <= 0L)return false;final long deadline = System.nanoTime() + nanosTimeout;final Node node = addWaiter(Node.SHARED);boolean failed = true;try {for (;;) {final Node p = node.predecessor();if (p == head) {int r = tryAcquireShared(arg);if (r >= 0) {setHeadAndPropagate(node, r);p.next = null; // help GCfailed = false;return true;}}nanosTimeout = deadline - System.nanoTime();if (nanosTimeout <= 0L)return false;if (shouldParkAfterFailedAcquire(p, node) &&nanosTimeout > spinForTimeoutThreshold)LockSupport.parkNanos(this, nanosTimeout);if (Thread.interrupted())throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}}// Main exported methods/*** Attempts to acquire in exclusive mode. This method should query* if the state of the object permits it to be acquired in the* exclusive mode, and if so to acquire it.** <p>This method is always invoked by the thread performing* acquire.  If this method reports failure, the acquire method* may queue the thread, if it is not already queued, until it is* signalled by a release from some other thread. This can be used* to implement method {@link Lock#tryLock()}.** <p>The default* implementation throws {@link UnsupportedOperationException}.** @param arg the acquire argument. This value is always the one*        passed to an acquire method, or is the value saved on entry*        to a condition wait.  The value is otherwise uninterpreted*        and can represent anything you like.* @return {@code true} if successful. Upon success, this object has*         been acquired.* @throws IllegalMonitorStateException if acquiring would place this*         synchronizer in an illegal state. This exception must be*         thrown in a consistent fashion for synchronization to work*         correctly.* @throws UnsupportedOperationException if exclusive mode is not supported*/protected boolean tryAcquire(int arg) {throw new UnsupportedOperationException();}/*** Attempts to set the state to reflect a release in exclusive* mode.** <p>This method is always invoked by the thread performing release.** <p>The default implementation throws* {@link UnsupportedOperationException}.** @param arg the release argument. This value is always the one*        passed to a release method, or the current state value upon*        entry to a condition wait.  The value is otherwise*        uninterpreted and can represent anything you like.* @return {@code true} if this object is now in a fully released*         state, so that any waiting threads may attempt to acquire;*         and {@code false} otherwise.* @throws IllegalMonitorStateException if releasing would place this*         synchronizer in an illegal state. This exception must be*         thrown in a consistent fashion for synchronization to work*         correctly.* @throws UnsupportedOperationException if exclusive mode is not supported*/protected boolean tryRelease(int arg) {throw new UnsupportedOperationException();}/*** Attempts to acquire in shared mode. This method should query if* the state of the object permits it to be acquired in the shared* mode, and if so to acquire it.** <p>This method is always invoked by the thread performing* acquire.  If this method reports failure, the acquire method* may queue the thread, if it is not already queued, until it is* signalled by a release from some other thread.** <p>The default implementation throws {@link* UnsupportedOperationException}.** @param arg the acquire argument. This value is always the one*        passed to an acquire method, or is the value saved on entry*        to a condition wait.  The value is otherwise uninterpreted*        and can represent anything you like.* @return a negative value on failure; zero if acquisition in shared*         mode succeeded but no subsequent shared-mode acquire can*         succeed; and a positive value if acquisition in shared*         mode succeeded and subsequent shared-mode acquires might*         also succeed, in which case a subsequent waiting thread*         must check availability. (Support for three different*         return values enables this method to be used in contexts*         where acquires only sometimes act exclusively.)  Upon*         success, this object has been acquired.* @throws IllegalMonitorStateException if acquiring would place this*         synchronizer in an illegal state. This exception must be*         thrown in a consistent fashion for synchronization to work*         correctly.* @throws UnsupportedOperationException if shared mode is not supported*/protected int tryAcquireShared(int arg) {throw new UnsupportedOperationException();}/*** Attempts to set the state to reflect a release in shared mode.** <p>This method is always invoked by the thread performing release.** <p>The default implementation throws* {@link UnsupportedOperationException}.** @param arg the release argument. This value is always the one*        passed to a release method, or the current state value upon*        entry to a condition wait.  The value is otherwise*        uninterpreted and can represent anything you like.* @return {@code true} if this release of shared mode may permit a*         waiting acquire (shared or exclusive) to succeed; and*         {@code false} otherwise* @throws IllegalMonitorStateException if releasing would place this*         synchronizer in an illegal state. This exception must be*         thrown in a consistent fashion for synchronization to work*         correctly.* @throws UnsupportedOperationException if shared mode is not supported*/protected boolean tryReleaseShared(int arg) {throw new UnsupportedOperationException();}/*** Returns {@code true} if synchronization is held exclusively with* respect to the current (calling) thread.  This method is invoked* upon each call to a non-waiting {@link ConditionObject} method.* (Waiting methods instead invoke {@link #release}.)** <p>The default implementation throws {@link* UnsupportedOperationException}. This method is invoked* internally only within {@link ConditionObject} methods, so need* not be defined if conditions are not used.** @return {@code true} if synchronization is held exclusively;*         {@code false} otherwise* @throws UnsupportedOperationException if conditions are not supported*/protected boolean isHeldExclusively() {throw new UnsupportedOperationException();}/*** Acquires in exclusive mode, ignoring interrupts.  Implemented* by invoking at least once {@link #tryAcquire},* returning on success.  Otherwise the thread is queued, possibly* repeatedly blocking and unblocking, invoking {@link* #tryAcquire} until success.  This method can be used* to implement method {@link Lock#lock}.** @param arg the acquire argument.  This value is conveyed to*        {@link #tryAcquire} but is otherwise uninterpreted and*        can represent anything you like.*/public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}/*** Acquires in exclusive mode, aborting if interrupted.* Implemented by first checking interrupt status, then invoking* at least once {@link #tryAcquire}, returning on* success.  Otherwise the thread is queued, possibly repeatedly* blocking and unblocking, invoking {@link #tryAcquire}* until success or the thread is interrupted.  This method can be* used to implement method {@link Lock#lockInterruptibly}.** @param arg the acquire argument.  This value is conveyed to*        {@link #tryAcquire} but is otherwise uninterpreted and*        can represent anything you like.* @throws InterruptedException if the current thread is interrupted*/public final void acquireInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();if (!tryAcquire(arg))doAcquireInterruptibly(arg);}/*** Attempts to acquire in exclusive mode, aborting if interrupted,* and failing if the given timeout elapses.  Implemented by first* checking interrupt status, then invoking at least once {@link* #tryAcquire}, returning on success.  Otherwise, the thread is* queued, possibly repeatedly blocking and unblocking, invoking* {@link #tryAcquire} until success or the thread is interrupted* or the timeout elapses.  This method can be used to implement* method {@link Lock#tryLock(long, TimeUnit)}.** @param arg the acquire argument.  This value is conveyed to*        {@link #tryAcquire} but is otherwise uninterpreted and*        can represent anything you like.* @param nanosTimeout the maximum number of nanoseconds to wait* @return {@code true} if acquired; {@code false} if timed out* @throws InterruptedException if the current thread is interrupted*/public final boolean tryAcquireNanos(int arg, long nanosTimeout)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();return tryAcquire(arg) ||doAcquireNanos(arg, nanosTimeout);}/*** Releases in exclusive mode.  Implemented by unblocking one or* more threads if {@link #tryRelease} returns true.* This method can be used to implement method {@link Lock#unlock}.** @param arg the release argument.  This value is conveyed to*        {@link #tryRelease} but is otherwise uninterpreted and*        can represent anything you like.* @return the value returned from {@link #tryRelease}*/public final boolean release(int arg) {if (tryRelease(arg)) {Node h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h);return true;}return false;}/*** Acquires in shared mode, ignoring interrupts.  Implemented by* first invoking at least once {@link #tryAcquireShared},* returning on success.  Otherwise the thread is queued, possibly* repeatedly blocking and unblocking, invoking {@link* #tryAcquireShared} until success.** @param arg the acquire argument.  This value is conveyed to*        {@link #tryAcquireShared} but is otherwise uninterpreted*        and can represent anything you like.*/public final void acquireShared(int arg) {if (tryAcquireShared(arg) < 0)doAcquireShared(arg);}/*** Acquires in shared mode, aborting if interrupted.  Implemented* by first checking interrupt status, then invoking at least once* {@link #tryAcquireShared}, returning on success.  Otherwise the* thread is queued, possibly repeatedly blocking and unblocking,* invoking {@link #tryAcquireShared} until success or the thread* is interrupted.* @param arg the acquire argument.* This value is conveyed to {@link #tryAcquireShared} but is* otherwise uninterpreted and can represent anything* you like.* @throws InterruptedException if the current thread is interrupted*/public final void acquireSharedInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();if (tryAcquireShared(arg) < 0)doAcquireSharedInterruptibly(arg);}/*** Attempts to acquire in shared mode, aborting if interrupted, and* failing if the given timeout elapses.  Implemented by first* checking interrupt status, then invoking at least once {@link* #tryAcquireShared}, returning on success.  Otherwise, the* thread is queued, possibly repeatedly blocking and unblocking,* invoking {@link #tryAcquireShared} until success or the thread* is interrupted or the timeout elapses.** @param arg the acquire argument.  This value is conveyed to*        {@link #tryAcquireShared} but is otherwise uninterpreted*        and can represent anything you like.* @param nanosTimeout the maximum number of nanoseconds to wait* @return {@code true} if acquired; {@code false} if timed out* @throws InterruptedException if the current thread is interrupted*/public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();return tryAcquireShared(arg) >= 0 ||doAcquireSharedNanos(arg, nanosTimeout);}/*** Releases in shared mode.  Implemented by unblocking one or more* threads if {@link #tryReleaseShared} returns true.** @param arg the release argument.  This value is conveyed to*        {@link #tryReleaseShared} but is otherwise uninterpreted*        and can represent anything you like.* @return the value returned from {@link #tryReleaseShared}*/public final boolean releaseShared(int arg) {if (tryReleaseShared(arg)) {doReleaseShared();return true;}return false;}// Queue inspection methods/*** Queries whether any threads are waiting to acquire. Note that* because cancellations due to interrupts and timeouts may occur* at any time, a {@code true} return does not guarantee that any* other thread will ever acquire.** <p>In this implementation, this operation returns in* constant time.** @return {@code true} if there may be other threads waiting to acquire*/public final boolean hasQueuedThreads() {return head != tail;}/*** Queries whether any threads have ever contended to acquire this* synchronizer; that is if an acquire method has ever blocked.** <p>In this implementation, this operation returns in* constant time.** @return {@code true} if there has ever been contention*/public final boolean hasContended() {return head != null;}/*** Returns the first (longest-waiting) thread in the queue, or* {@code null} if no threads are currently queued.** <p>In this implementation, this operation normally returns in* constant time, but may iterate upon contention if other threads are* concurrently modifying the queue.** @return the first (longest-waiting) thread in the queue, or*         {@code null} if no threads are currently queued*/public final Thread getFirstQueuedThread() {// handle only fast path, else relayreturn (head == tail) ? null : fullGetFirstQueuedThread();}/*** Version of getFirstQueuedThread called when fastpath fails*/private Thread fullGetFirstQueuedThread() {/** The first node is normally head.next. Try to get its* thread field, ensuring consistent reads: If thread* field is nulled out or s.prev is no longer head, then* some other thread(s) concurrently performed setHead in* between some of our reads. We try this twice before* resorting to traversal.*/Node h, s;Thread st;if (((h = head) != null && (s = h.next) != null &&s.prev == head && (st = s.thread) != null) ||((h = head) != null && (s = h.next) != null &&s.prev == head && (st = s.thread) != null))return st;/** Head's next field might not have been set yet, or may have* been unset after setHead. So we must check to see if tail* is actually first node. If not, we continue on, safely* traversing from tail back to head to find first,* guaranteeing termination.*/Node t = tail;Thread firstThread = null;while (t != null && t != head) {Thread tt = t.thread;if (tt != null)firstThread = tt;t = t.prev;}return firstThread;}/*** Returns true if the given thread is currently queued.** <p>This implementation traverses the queue to determine* presence of the given thread.** @param thread the thread* @return {@code true} if the given thread is on the queue* @throws NullPointerException if the thread is null*/public final boolean isQueued(Thread thread) {if (thread == null)throw new NullPointerException();for (Node p = tail; p != null; p = p.prev)if (p.thread == thread)return true;return false;}/*** Returns {@code true} if the apparent first queued thread, if one* exists, is waiting in exclusive mode.  If this method returns* {@code true}, and the current thread is attempting to acquire in* shared mode (that is, this method is invoked from {@link* #tryAcquireShared}) then it is guaranteed that the current thread* is not the first queued thread.  Used only as a heuristic in* ReentrantReadWriteLock.*/final boolean apparentlyFirstQueuedIsExclusive() {Node h, s;return (h = head) != null &&(s = h.next)  != null &&!s.isShared()         &&s.thread != null;}/*** Queries whether any threads have been waiting to acquire longer* than the current thread.** <p>An invocation of this method is equivalent to (but may be* more efficient than):*  <pre> {@code* getFirstQueuedThread() != Thread.currentThread() &&* hasQueuedThreads()}</pre>** <p>Note that because cancellations due to interrupts and* timeouts may occur at any time, a {@code true} return does not* guarantee that some other thread will acquire before the current* thread.  Likewise, it is possible for another thread to win a* race to enqueue after this method has returned {@code false},* due to the queue being empty.** <p>This method is designed to be used by a fair synchronizer to* avoid <a href="AbstractQueuedSynchronizer#barging">barging</a>.* Such a synchronizer's {@link #tryAcquire} method should return* {@code false}, and its {@link #tryAcquireShared} method should* return a negative value, if this method returns {@code true}* (unless this is a reentrant acquire).  For example, the {@code* tryAcquire} method for a fair, reentrant, exclusive mode* synchronizer might look like this:**  <pre> {@code* protected boolean tryAcquire(int arg) {*   if (isHeldExclusively()) {*     // A reentrant acquire; increment hold count*     return true;*   } else if (hasQueuedPredecessors()) {*     return false;*   } else {*     // try to acquire normally*   }* }}</pre>** @return {@code true} if there is a queued thread preceding the*         current thread, and {@code false} if the current thread*         is at the head of the queue or the queue is empty* @since 1.7*/public final boolean hasQueuedPredecessors() {// The correctness of this depends on head being initialized// before tail and on head.next being accurate if the current// thread is first in queue.Node t = tail; // Read fields in reverse initialization orderNode h = head;Node s;return h != t &&((s = h.next) == null || s.thread != Thread.currentThread());}// Instrumentation and monitoring methods/*** Returns an estimate of the number of threads waiting to* acquire.  The value is only an estimate because the number of* threads may change dynamically while this method traverses* internal data structures.  This method is designed for use in* monitoring system state, not for synchronization* control.** @return the estimated number of threads waiting to acquire*/public final int getQueueLength() {int n = 0;for (Node p = tail; p != null; p = p.prev) {if (p.thread != null)++n;}return n;}/*** Returns a collection containing threads that may be waiting to* acquire.  Because the actual set of threads may change* dynamically while constructing this result, the returned* collection is only a best-effort estimate.  The elements of the* returned collection are in no particular order.  This method is* designed to facilitate construction of subclasses that provide* more extensive monitoring facilities.** @return the collection of threads*/public final Collection<Thread> getQueuedThreads() {ArrayList<Thread> list = new ArrayList<Thread>();for (Node p = tail; p != null; p = p.prev) {Thread t = p.thread;if (t != null)list.add(t);}return list;}/*** Returns a collection containing threads that may be waiting to* acquire in exclusive mode. This has the same properties* as {@link #getQueuedThreads} except that it only returns* those threads waiting due to an exclusive acquire.** @return the collection of threads*/public final Collection<Thread> getExclusiveQueuedThreads() {ArrayList<Thread> list = new ArrayList<Thread>();for (Node p = tail; p != null; p = p.prev) {if (!p.isShared()) {Thread t = p.thread;if (t != null)list.add(t);}}return list;}/*** Returns a collection containing threads that may be waiting to* acquire in shared mode. This has the same properties* as {@link #getQueuedThreads} except that it only returns* those threads waiting due to a shared acquire.** @return the collection of threads*/public final Collection<Thread> getSharedQueuedThreads() {ArrayList<Thread> list = new ArrayList<Thread>();for (Node p = tail; p != null; p = p.prev) {if (p.isShared()) {Thread t = p.thread;if (t != null)list.add(t);}}return list;}/*** Returns a string identifying this synchronizer, as well as its state.* The state, in brackets, includes the String {@code "State ="}* followed by the current value of {@link #getState}, and either* {@code "nonempty"} or {@code "empty"} depending on whether the* queue is empty.** @return a string identifying this synchronizer, as well as its state*/public String toString() {int s = getState();String q  = hasQueuedThreads() ? "non" : "";return super.toString() +"[State = " + s + ", " + q + "empty queue]";}// Internal support methods for Conditions/*** Returns true if a node, always one that was initially placed on* a condition queue, is now waiting to reacquire on sync queue.* @param node the node* @return true if is reacquiring*/final boolean isOnSyncQueue(Node node) {if (node.waitStatus == Node.CONDITION || node.prev == null)return false;if (node.next != null) // If has successor, it must be on queuereturn true;/** node.prev can be non-null, but not yet on queue because* the CAS to place it on queue can fail. So we have to* traverse from tail to make sure it actually made it.  It* will always be near the tail in calls to this method, and* unless the CAS failed (which is unlikely), it will be* there, so we hardly ever traverse much.*/return findNodeFromTail(node);}/*** Returns true if node is on sync queue by searching backwards from tail.* Called only when needed by isOnSyncQueue.* @return true if present*/private boolean findNodeFromTail(Node node) {Node t = tail;for (;;) {if (t == node)return true;if (t == null)return false;t = t.prev;}}/*** Transfers a node from a condition queue onto sync queue.* Returns true if successful.* @param node the node* @return true if successfully transferred (else the node was* cancelled before signal)*/final boolean transferForSignal(Node node) {/** If cannot change waitStatus, the node has been cancelled.*/if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))return false;/** Splice onto queue and try to set waitStatus of predecessor to* indicate that thread is (probably) waiting. If cancelled or* attempt to set waitStatus fails, wake up to resync (in which* case the waitStatus can be transiently and harmlessly wrong).*/Node p = enq(node);int ws = p.waitStatus;if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))LockSupport.unpark(node.thread);return true;}/*** Transfers node, if necessary, to sync queue after a cancelled wait.* Returns true if thread was cancelled before being signalled.** @param node the node* @return true if cancelled before the node was signalled*/final boolean transferAfterCancelledWait(Node node) {if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {enq(node);return true;}/** If we lost out to a signal(), then we can't proceed* until it finishes its enq().  Cancelling during an* incomplete transfer is both rare and transient, so just* spin.*/while (!isOnSyncQueue(node))Thread.yield();return false;}/*** Invokes release with current state value; returns saved state.* Cancels node and throws exception on failure.* @param node the condition node for this wait* @return previous sync state*/final int fullyRelease(Node node) {boolean failed = true;try {int savedState = getState();if (release(savedState)) {failed = false;return savedState;} else {throw new IllegalMonitorStateException();}} finally {if (failed)node.waitStatus = Node.CANCELLED;}}// Instrumentation methods for conditions/*** Queries whether the given ConditionObject* uses this synchronizer as its lock.** @param condition the condition* @return {@code true} if owned* @throws NullPointerException if the condition is null*/public final boolean owns(ConditionObject condition) {return condition.isOwnedBy(this);}/*** Queries whether any threads are waiting on the given condition* associated with this synchronizer. Note that because timeouts* and interrupts may occur at any time, a {@code true} return* does not guarantee that a future {@code signal} will awaken* any threads.  This method is designed primarily for use in* monitoring of the system state.** @param condition the condition* @return {@code true} if there are any waiting threads* @throws IllegalMonitorStateException if exclusive synchronization*         is not held* @throws IllegalArgumentException if the given condition is*         not associated with this synchronizer* @throws NullPointerException if the condition is null*/public final boolean hasWaiters(ConditionObject condition) {if (!owns(condition))throw new IllegalArgumentException("Not owner");return condition.hasWaiters();}/*** Returns an estimate of the number of threads waiting on the* given condition associated with this synchronizer. Note that* because timeouts and interrupts may occur at any time, the* estimate serves only as an upper bound on the actual number of* waiters.  This method is designed for use in monitoring of the* system state, not for synchronization control.** @param condition the condition* @return the estimated number of waiting threads* @throws IllegalMonitorStateException if exclusive synchronization*         is not held* @throws IllegalArgumentException if the given condition is*         not associated with this synchronizer* @throws NullPointerException if the condition is null*/public final int getWaitQueueLength(ConditionObject condition) {if (!owns(condition))throw new IllegalArgumentException("Not owner");return condition.getWaitQueueLength();}/*** Returns a collection containing those threads that may be* waiting on the given condition associated with this* synchronizer.  Because the actual set of threads may change* dynamically while constructing this result, the returned* collection is only a best-effort estimate. The elements of the* returned collection are in no particular order.** @param condition the condition* @return the collection of threads* @throws IllegalMonitorStateException if exclusive synchronization*         is not held* @throws IllegalArgumentException if the given condition is*         not associated with this synchronizer* @throws NullPointerException if the condition is null*/public final Collection<Thread> getWaitingThreads(ConditionObject condition) {if (!owns(condition))throw new IllegalArgumentException("Not owner");return condition.getWaitingThreads();}/*** Condition implementation for a {@link* AbstractQueuedSynchronizer} serving as the basis of a {@link* Lock} implementation.** <p>Method documentation for this class describes mechanics,* not behavioral specifications from the point of view of Lock* and Condition users. Exported versions of this class will in* general need to be accompanied by documentation describing* condition semantics that rely on those of the associated* {@code AbstractQueuedSynchronizer}.** <p>This class is Serializable, but all fields are transient,* so deserialized conditions have no waiters.*/public class ConditionObject implements Condition, java.io.Serializable {private static final long serialVersionUID = 1173984872572414699L;/** First node of condition queue. */private transient Node firstWaiter;/** Last node of condition queue. */private transient Node lastWaiter;/*** Creates a new {@code ConditionObject} instance.*/public ConditionObject() { }// Internal methods/*** Adds a new waiter to wait queue.* @return its new wait node*/private Node addConditionWaiter() {Node t = lastWaiter;// If lastWaiter is cancelled, clean out.if (t != null && t.waitStatus != Node.CONDITION) {unlinkCancelledWaiters();t = lastWaiter;}Node node = new Node(Thread.currentThread(), Node.CONDITION);if (t == null)firstWaiter = node;elset.nextWaiter = node;lastWaiter = node;return node;}/*** Removes and transfers nodes until hit non-cancelled one or* null. Split out from signal in part to encourage compilers* to inline the case of no waiters.* @param first (non-null) the first node on condition queue*/private void doSignal(Node first) {do {if ( (firstWaiter = first.nextWaiter) == null)lastWaiter = null;first.nextWaiter = null;} while (!transferForSignal(first) &&(first = firstWaiter) != null);}/*** Removes and transfers all nodes.* @param first (non-null) the first node on condition queue*/private void doSignalAll(Node first) {lastWaiter = firstWaiter = null;do {Node next = first.nextWaiter;first.nextWaiter = null;transferForSignal(first);first = next;} while (first != null);}/*** Unlinks cancelled waiter nodes from condition queue.* Called only while holding lock. This is called when* cancellation occurred during condition wait, and upon* insertion of a new waiter when lastWaiter is seen to have* been cancelled. This method is needed to avoid garbage* retention in the absence of signals. So even though it may* require a full traversal, it comes into play only when* timeouts or cancellations occur in the absence of* signals. It traverses all nodes rather than stopping at a* particular target to unlink all pointers to garbage nodes* without requiring many re-traversals during cancellation* storms.*/private void unlinkCancelledWaiters() {Node t = firstWaiter;Node trail = null;while (t != null) {Node next = t.nextWaiter;if (t.waitStatus != Node.CONDITION) {t.nextWaiter = null;if (trail == null)firstWaiter = next;elsetrail.nextWaiter = next;if (next == null)lastWaiter = trail;}elsetrail = t;t = next;}}// public methods/*** Moves the longest-waiting thread, if one exists, from the* wait queue for this condition to the wait queue for the* owning lock.** @throws IllegalMonitorStateException if {@link #isHeldExclusively}*         returns {@code false}*/public final void signal() {if (!isHeldExclusively())throw new IllegalMonitorStateException();Node first = firstWaiter;if (first != null)doSignal(first);}/*** Moves all threads from the wait queue for this condition to* the wait queue for the owning lock.** @throws IllegalMonitorStateException if {@link #isHeldExclusively}*         returns {@code false}*/public final void signalAll() {if (!isHeldExclusively())throw new IllegalMonitorStateException();Node first = firstWaiter;if (first != null)doSignalAll(first);}/*** Implements uninterruptible condition wait.* <ol>* <li> Save lock state returned by {@link #getState}.* <li> Invoke {@link #release} with saved state as argument,*      throwing IllegalMonitorStateException if it fails.* <li> Block until signalled.* <li> Reacquire by invoking specialized version of*      {@link #acquire} with saved state as argument.* </ol>*/public final void awaitUninterruptibly() {Node node = addConditionWaiter();int savedState = fullyRelease(node);boolean interrupted = false;while (!isOnSyncQueue(node)) {LockSupport.park(this);if (Thread.interrupted())interrupted = true;}if (acquireQueued(node, savedState) || interrupted)selfInterrupt();}/** For interruptible waits, we need to track whether to throw* InterruptedException, if interrupted while blocked on* condition, versus reinterrupt current thread, if* interrupted while blocked waiting to re-acquire.*//** Mode meaning to reinterrupt on exit from wait */private static final int REINTERRUPT =  1;/** Mode meaning to throw InterruptedException on exit from wait */private static final int THROW_IE    = -1;/*** Checks for interrupt, returning THROW_IE if interrupted* before signalled, REINTERRUPT if after signalled, or* 0 if not interrupted.*/private int checkInterruptWhileWaiting(Node node) {return Thread.interrupted() ?(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :0;}/*** Throws InterruptedException, reinterrupts current thread, or* does nothing, depending on mode.*/private void reportInterruptAfterWait(int interruptMode)throws InterruptedException {if (interruptMode == THROW_IE)throw new InterruptedException();else if (interruptMode == REINTERRUPT)selfInterrupt();}/*** Implements interruptible condition wait.* <ol>* <li> If current thread is interrupted, throw InterruptedException.* <li> Save lock state returned by {@link #getState}.* <li> Invoke {@link #release} with saved state as argument,*      throwing IllegalMonitorStateException if it fails.* <li> Block until signalled or interrupted.* <li> Reacquire by invoking specialized version of*      {@link #acquire} with saved state as argument.* <li> If interrupted while blocked in step 4, throw InterruptedException.* </ol>*/public final void await() throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter();int savedState = fullyRelease(node);int interruptMode = 0;while (!isOnSyncQueue(node)) {LockSupport.park(this);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;if (node.nextWaiter != null) // clean up if cancelledunlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode);}/*** Implements timed condition wait.* <ol>* <li> If current thread is interrupted, throw InterruptedException.* <li> Save lock state returned by {@link #getState}.* <li> Invoke {@link #release} with saved state as argument,*      throwing IllegalMonitorStateException if it fails.* <li> Block until signalled, interrupted, or timed out.* <li> Reacquire by invoking specialized version of*      {@link #acquire} with saved state as argument.* <li> If interrupted while blocked in step 4, throw InterruptedException.* </ol>*/public final long awaitNanos(long nanosTimeout)throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter();int savedState = fullyRelease(node);final long deadline = System.nanoTime() + nanosTimeout;int interruptMode = 0;while (!isOnSyncQueue(node)) {if (nanosTimeout <= 0L) {transferAfterCancelledWait(node);break;}if (nanosTimeout >= spinForTimeoutThreshold)LockSupport.parkNanos(this, nanosTimeout);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;nanosTimeout = deadline - System.nanoTime();}if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;if (node.nextWaiter != null)unlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode);return deadline - System.nanoTime();}/*** Implements absolute timed condition wait.* <ol>* <li> If current thread is interrupted, throw InterruptedException.* <li> Save lock state returned by {@link #getState}.* <li> Invoke {@link #release} with saved state as argument,*      throwing IllegalMonitorStateException if it fails.* <li> Block until signalled, interrupted, or timed out.* <li> Reacquire by invoking specialized version of*      {@link #acquire} with saved state as argument.* <li> If interrupted while blocked in step 4, throw InterruptedException.* <li> If timed out while blocked in step 4, return false, else true.* </ol>*/public final boolean awaitUntil(Date deadline)throws InterruptedException {long abstime = deadline.getTime();if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter();int savedState = fullyRelease(node);boolean timedout = false;int interruptMode = 0;while (!isOnSyncQueue(node)) {if (System.currentTimeMillis() > abstime) {timedout = transferAfterCancelledWait(node);break;}LockSupport.parkUntil(this, abstime);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;}if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;if (node.nextWaiter != null)unlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode);return !timedout;}/*** Implements timed condition wait.* <ol>* <li> If current thread is interrupted, throw InterruptedException.* <li> Save lock state returned by {@link #getState}.* <li> Invoke {@link #release} with saved state as argument,*      throwing IllegalMonitorStateException if it fails.* <li> Block until signalled, interrupted, or timed out.* <li> Reacquire by invoking specialized version of*      {@link #acquire} with saved state as argument.* <li> If interrupted while blocked in step 4, throw InterruptedException.* <li> If timed out while blocked in step 4, return false, else true.* </ol>*/public final boolean await(long time, TimeUnit unit)throws InterruptedException {long nanosTimeout = unit.toNanos(time);if (Thread.interrupted())throw new InterruptedException();Node node = addConditionWaiter();int savedState = fullyRelease(node);final long deadline = System.nanoTime() + nanosTimeout;boolean timedout = false;int interruptMode = 0;while (!isOnSyncQueue(node)) {if (nanosTimeout <= 0L) {timedout = transferAfterCancelledWait(node);break;}if (nanosTimeout >= spinForTimeoutThreshold)LockSupport.parkNanos(this, nanosTimeout);if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)break;nanosTimeout = deadline - System.nanoTime();}if (acquireQueued(node, savedState) && interruptMode != THROW_IE)interruptMode = REINTERRUPT;if (node.nextWaiter != null)unlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode);return !timedout;}//  support for instrumentation/*** Returns true if this condition was created by the given* synchronization object.** @return {@code true} if owned*/final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {return sync == AbstractQueuedSynchronizer.this;}/*** Queries whether any threads are waiting on this condition.* Implements {@link AbstractQueuedSynchronizer#hasWaiters(ConditionObject)}.** @return {@code true} if there are any waiting threads* @throws IllegalMonitorStateException if {@link #isHeldExclusively}*         returns {@code false}*/protected final boolean hasWaiters() {if (!isHeldExclusively())throw new IllegalMonitorStateException();for (Node w = firstWaiter; w != null; w = w.nextWaiter) {if (w.waitStatus == Node.CONDITION)return true;}return false;}/*** Returns an estimate of the number of threads waiting on* this condition.* Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)}.** @return the estimated number of waiting threads* @throws IllegalMonitorStateException if {@link #isHeldExclusively}*         returns {@code false}*/protected final int getWaitQueueLength() {if (!isHeldExclusively())throw new IllegalMonitorStateException();int n = 0;for (Node w = firstWaiter; w != null; w = w.nextWaiter) {if (w.waitStatus == Node.CONDITION)++n;}return n;}/*** Returns a collection containing those threads that may be* waiting on this Condition.* Implements {@link AbstractQueuedSynchronizer#getWaitingThreads(ConditionObject)}.** @return the collection of threads* @throws IllegalMonitorStateException if {@link #isHeldExclusively}*         returns {@code false}*/protected final Collection<Thread> getWaitingThreads() {if (!isHeldExclusively())throw new IllegalMonitorStateException();ArrayList<Thread> list = new ArrayList<Thread>();for (Node w = firstWaiter; w != null; w = w.nextWaiter) {if (w.waitStatus == Node.CONDITION) {Thread t = w.thread;if (t != null)list.add(t);}}return list;}}/*** Setup to support compareAndSet. We need to natively implement* this here: For the sake of permitting future enhancements, we* cannot explicitly subclass AtomicInteger, which would be* efficient and useful otherwise. So, as the lesser of evils, we* natively implement using hotspot intrinsics API. And while we* are at it, we do the same for other CASable fields (which could* otherwise be done with atomic field updaters).*/private static final Unsafe unsafe = Unsafe.getUnsafe();private static final long stateOffset;private static final long headOffset;private static final long tailOffset;private static final long waitStatusOffset;private static final long nextOffset;static {try {stateOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("state"));headOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("head"));tailOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));waitStatusOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("waitStatus"));nextOffset = unsafe.objectFieldOffset(Node.class.getDeclaredField("next"));} catch (Exception ex) { throw new Error(ex); }}/*** CAS head field. Used only by enq.*/private final boolean compareAndSetHead(Node update) {return unsafe.compareAndSwapObject(this, headOffset, null, update);}/*** CAS tail field. Used only by enq.*/private final boolean compareAndSetTail(Node expect, Node update) {return unsafe.compareAndSwapObject(this, tailOffset, expect, update);}/*** CAS waitStatus field of a node.*/private static final boolean compareAndSetWaitStatus(Node node,int expect,int update) {return unsafe.compareAndSwapInt(node, waitStatusOffset,expect, update);}/*** CAS next field of a node.*/private static final boolean compareAndSetNext(Node node,Node expect,Node update) {return unsafe.compareAndSwapObject(node, nextOffset, expect, update);}
}
  • AQS的父类AbstractOwnableSynchronizer里面定义了一个变量 private transient Thread exclusiveOwnerThread;,可以判断当前获取锁的线程是哪个。

  • AQS类中定义了一个变量private volatile int state(默认为0);可以判断当前同步器状态。为0表示当前锁没有被线程持有,可以进行加锁。

  • AQS中定义了一个内部类Node–private transient volatile Node head;,基于这个Node实现了一个双向链表的队列。次内部类中定义了两个变量volatile Node prev; volatile Node next;用来实现双向链表。prev指向此Node的上一个节点,next指向下一个节点。

  • AQS中还有两个属性,private transient volatile Node head;private transient volatile Node tail;分别指向队列的队头和队尾。

  • Node内部类中还有一个线程的引用volatile Thread thread;

  • ReentrantLock具体加锁过程




lock方法—>内部类Sync的 sync.lock();—>公平锁(FairSync(Sync的内部类))的lock方法—>AQS中的acquire(1);—>tryAcquire(尝试获取锁)
tryAcquire方法获取锁过程如下

1:获取当前线程
2: 获取state的值
如果为0,允许被持有锁,判断是否有线程排队,通过CAS修改State值,并且讲当前线程的引用赋值给exclusiveOwnerThread表示锁被当前线程持有。
如果不为0,查看当前锁是否被自己线程持有,有的话state+1,不是被自己持有就直接返回FALSE,表示加锁失败。
加锁失败就阻塞等待。–加入等待队列。

05.抽象队列同步器AQS应用之Lock详解相关推荐

  1. 【学习笔记】抽象队列同步器AQS应用之BlockingQueue详解

    文章目录 什么是AQS框架 Aqs核心源码 基于aqs实现的锁 BlockingQueue ArrayBlockingQueue LinkedBlockingQueue DelayQueue Bloc ...

  2. 六:抽象队列同步器AQS应用之BlockingQueue详解

    目录 概要 队列类型 队列数据结构 ArrayBlockingQueue LinkedBlockingQueue DelayQueue BlockingQueue API 多线程生产者-消费者示例 并 ...

  3. 并发——抽象队列同步器AQS的实现原理

    一.前言 这段时间在研究Java并发相关的内容,一段时间下来算是小有收获了.ReentrantLock是Java并发中的重要部分,所以也是我的首要研究对象,在学习它的过程中,我发现它是基于抽象队列同步 ...

  4. 并发编程-15并发容器(J.U.C)核心 AbstractQueuedSynchronizer 抽象队列同步器AQS介绍

    文章目录 J.U.C脑图 J.U.C核心AQS简介 AQS底层数据结构 AQS特点 J.U.C脑图 为了体现出AQS和线程池的重要性,上图单独将AQS和线程池拿出来了. J.U.C的构成如下: J.U ...

  5. AQS抽象队列同步器原理详解

    系列文章目录 第一节 synchronized关键字详解-偏向锁.轻量级锁.偏向锁.重量级锁.自旋.锁粗化.锁消除 AQS抽象队列同步器原理详解 系列文章目录 前言 一.AQS特性 二.AQS原理 1 ...

  6. JUC多线程:AQS抽象队列同步器原理

    一.AQS 的工作原理: 1.1.什么是 AQS: AQS,Abstract Queued Synchronizer,抽象队列同步器,是 J.U.C 中实现锁及同步组件的基础.工作原理就是如果被请求的 ...

  7. Java并发编程之AbstractQueuedSychronizer(抽象队列同步器,简称AQS)

    AbstractQueuedSychronizer(抽象队列同步器,简称AQS): JDK的并发包(包名:java.util.concurrent,以下简称JUC)下面提供了很多并发操作的工具类,如: ...

  8. java同步队列_Java 中队列同步器 AQS(AbstractQueuedSynchronizer)实现原理

    前言 在 Java 中通过锁来控制多个线程对共享资源的访问,使用 Java 编程语言开发的朋友都知道,可以通过 synchronized 关键字来实现锁的功能,它可以隐式的获取锁,也就是说我们使用该关 ...

  9. C++11 并发指南三(Lock 详解)(转载)

    multithreading 多线程 C++11 C++11多线程基本使用 C++11 并发指南三(Lock 详解) 在 <C++11 并发指南三(std::mutex 详解)>一文中我们 ...

最新文章

  1. 2021年春季学期-信号与系统-第五次作业参考答案
  2. Spring.net与Asp.net Mvc结合示例《转载》
  3. python的对象模型_[ Python 源码剖析] 对象模型概述
  4. 深入理解mybatis原理, Mybatis初始化SqlSessionFactory机制详解(转)
  5. 九和一 Hidove聚合在线图床PHP源码
  6. 棋盘问题 POJ - 1321
  7. Codeforces 990G 点分治+暴力
  8. 树莓派 4B 配置 Ubuntu20.04 和 ROS2
  9. 精益创业(LeanStartup)
  10. matlab三水箱,基于MATLAB的三容水箱液位串级控制系统的设计(毕业设计)
  11. PHP实现简单的网站访客统计
  12. 云计算时代IT产业六大发展趋势
  13. ae导出html,动画还原100%-AE一键导出
  14. java版林地府邸种子_我的世界林地府邸地图种子代码分享
  15. Python中的PV操作
  16. prometheus-community-PushProx介绍
  17. python爬取boss直招_简易python爬虫爬取boss直聘职位,并写入excel
  18. Android 学习之那些年我们遇到的BUG1:This view is not constrained, it only has designtime positions
  19. STC8A8K64单片机关于AT24C04基本读写操作(包含硬件I2C与软件模拟I2C)
  20. 单片机的特殊功能寄存器

热门文章

  1. 工业交换机智能监控管理方案
  2. adb push文件夹
  3. GD32F303固件库开发(16)----移植兆易创新SPI Nor Flash之GD25Q64Flash
  4. 用C语言构造康托集,洛谷——P1014 Cantor表
  5. 【PMAC】Chapter3:COM类工厂中CLSD为{XXX}的组件失败
  6. Linux安装卸载Mysql与基本操作
  7. OLAP分析引擎Druid配置文件详解(五):MiddleManager配置文件
  8. 基于Faster-RCNN的目标检测(TF版) 步骤与问题解决办法
  9. HTTP就绪状态和HTTP状态码
  10. 怎样成为优秀的前端_如何成为优秀的在线社区会员