AbstractQueuedSynchronizer源码剖析(一)- 深刻解析与模拟线程竞争资源

1、细说AQS


      在深入分析AQS之前,我想先从AQS的功能上说明下AQS,站在使用者的角度,AQS的功能可以分为两类:独占锁和共享锁。它的所有子类中,要么实现并使用了它独占锁的API,要么使用了共享锁的API,而不会同时使用两套API,即便是它最有名的子类ReentrantReadWriteLock,也是通过两个内部类:读锁和写锁,分别实现的两套API来实现的,到目前为止,我们只需要明白AQS在功能上有独占锁和共享锁两种功能即可。

2、ReentrantLock的调用过程

AbstractQueuedSynchronizer中抽象了绝大多数Lock的功能,而只把tryAcquire方法延迟到子类中去实现。tryAcquire方法的语义在于用具体子类判断请求线程是否可以获得锁,无论成功与否AbstractQueuedSynchronizer都将处理后面的流程。

3、获取锁的过程

简单说来,AbstractQueuedSynchronizer会把所有的请求线程构成一个CLH队列,当一个线程执行完毕(lock.unlock())时会激活自己的后继节点,但正在执行的线程并不在队列中,而那些等待执行的线程全部处于阻塞状态。

 

4、非公平锁的加锁流程

(1). 首先我们分析非公平锁的的请求过程。我们假设在这个时候,还没有任务线程获取锁,这个时候,第一个线程过来了(我们使用的是非公平锁),那么第一个线程thread1会去获取锁,这时它会调用下面的方法,通过CAS的操作,将当前AQS的state由0变成1,证明当前thread1已经获取到锁,并且将AQS的exclusiveOwnerThread设置成thread1,证明当前持有锁的线程是thread1。

 1 /**
 2  * Performs lock.  Try immediate barge, backing up to normal
 3  * acquire on failure.
 4  */
 5 final void lock() {
 6     // 如果锁没有被任何线程锁定且加锁成功则设定当前线程为锁的拥有者
 7     if (compareAndSetState(0, 1))
 8         setExclusiveOwnerThread(Thread.currentThread());
 9     else
10         acquire(1);
11 }

(2). 此时来了第二个线程thread2,并且我们假设thread1还没有释放锁,因为我们使用的是非公平锁,那么thread2首先会进行抢占式的去获取锁,调用NonFairSync.lock方法获取锁。NonFairSync.lock方法的第一个分支是通过CAS操作获取锁,很明显,这一步肯定会失败,因为此时thread1还没有释放锁。那么thread2将会走NonFairSync.lock方法的第二个分支,进行acquire(1)操作。acquire(1)其实是AQS的方法,acquire(1)方法内部首先调用tryAcquire方法,ReentrantLock.NonFairLock重写了tryAcquire方法,并且ReentrantLock.NonFairLock的tryAcquire方法又调用了ReentrantLock.Sync的nonfairTryAcquire方法,nonfairTryAcquire方法如下:

 1 /**
 2 * Performs non-fair tryLock. tryAcquire is
 3 * implemented in subclasses, but both need nonfair
 4 * try for trylock method.
 5 */
 6 final boolean nonfairTryAcquire(int acquires) {
 7 final Thread current = Thread.currentThread();
 8 int c = getState();
 9 if (c == 0) {
10 if (compareAndSetState(0, acquires)) {
11 setExclusiveOwnerThread(current);
12 return true;
13 }
14 }
15 else if (current == getExclusiveOwnerThread()) {
16 int nextc = c + acquires;
17 if (nextc < 0) // overflow
18 throw new Error("Maximum lock count exceeded");
19 setState(nextc);
20 return true;
21 }
22 return false;
23 }

 

这个方法的执行逻辑如下:

1. 获取当前将要去获取锁的线程,在此时的情况下,也就是我们的thread2线程。

2. 获取当前AQS的state的值。如果此时state的值是0,那么我们就通过CAS操作获取锁,然后设置AQS的exclusiveOwnerThread为thread2。很明显,在当前的这个执行情况下,state的值是1不是0,因为我们的thread1还没有释放锁。

3. 如果当前将要去获取锁的线程等于此时AQS的exclusiveOwnerThread的线程,则此时将state的值加1,很明显这是重入锁的实现方式。在此时的运行状态下,将要去获取锁的线程不是thread1,也就是说这一步不成立。

4. 以上操作都不成立的话,我们直接返回false。

既然返回了false,那么之后就会调用addWaiter方法,这个方法负责把当前无法获取锁的线程包装为一个Node添加到队尾。通过下面的代码片段我们就知道调用逻辑:

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

我们进入到addWaiter方法内部去看:

 1 private Node addWaiter(Node mode) {
 2         Node node = new Node(Thread.currentThread(), mode);
 3         // Try the fast path of enq; backup to full enq on failure
 4         Node pred = tail;
 5         if (pred != null) {
 6             node.prev = pred;
 7             if (compareAndSetTail(pred, node)) {
 8                 pred.next = node;
 9                 return node;
10             }
11         }
12         enq(node);
13         return node;
14     }

很明显在addWaiter内部:
第一步:将当前将要去获取锁的线程也就是thread2和独占模式封装为一个node对象。并且我们也知道在当前的执行环境下,线程阻塞队列是空的,因为thread1获取了锁,thread2也是刚刚来请求锁,所以线程阻塞队列里面是空的。很明显,这个时候队列的尾部tail节点也是null,那么将直接进入到enq方法。

第二步:我们首先看下enq方法的内部实现。首先内部是一个自悬循环。

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

第一次循环:t为null,随后我们new出了一个空的node节点,并且通过CAS操作设置了线程的阻塞队列的head节点就是我们刚才new出来的那个空的node节点,其实这是一个“假节点”,那么什么是“假节点”呢?那就是节点中不包含线程。设置完head节点后,同时又将head节点赋值给尾部tail节点,到此第一次循环结束。此时的节点就是如下:

第二次循环:

 

现在判断尾部tail已经不是null了,那么就走第二个分支了。将尾部tail节点赋值给我们传递进来的节点Node的前驱节点,此时的结构如下:

然后再通过CAS的操作,将我们传递进来的节点node设置成尾部tail节点,并且将我们的node节点赋值给原来的老的那个尾部节点的后继节点,此时的结构如下:

这个时候代码中使用了return关键字,也就是证明我们经过了2次循环跳出了这个自悬循环体系。

按照代码的执行流程,接下来将会调用acquireQueued方法,主要是判断当前节点的前驱节点是不是head节点,如果是的话,就再去尝试获取锁,如果不是,就挂起当前线程。这里可能有人疑问了,为什么判断当前节点的前驱节点是head节点的话就去尝试获取锁呢?因为我们知道head节点是一个假节点,如果当前的节点的前驱节点是头节点即是假节点的话,那么这个假节点的后继节点就有可能有获取锁的机会,所以我们需要去尝试。

现在我们看下acquireQueued方法内部,我们也可以清楚的看到,这个方法的内部也是一个自悬循环。

 1 final boolean acquireQueued(final Node node, int arg) {
 2         boolean failed = true;
 3         try {
 4             boolean interrupted = false;
 5             for (;;) {
 6                 final Node p = node.predecessor();
 7                 if (p == head && tryAcquire(arg)) {
 8                     setHead(node);
 9                     p.next = null; // help GC
10                     failed = false;
11                     return interrupted;
12                 }
13                 if (shouldParkAfterFailedAcquire(p, node) &&
14                     parkAndCheckInterrupt())
15                     interrupted = true;
16             }
17         } finally {
18             if (failed)
19                 cancelAcquire(node);
20         }
21     }

第一次循环:获取我们传入node的前驱节点,判断是否是head节点,现在我们的状态是:

很明显满足当前node节点的前驱节点是head节点,那么现在我们就要去调用tryAcquire方法,也就是NonfairSync类的tryAcquire方法,而这个方法又调用了ReentrantLock.Sync.nonfairTryAcquire方法。

很明显此时thread2获取锁是失败的,直接返回false。按照调用流程,现在进入了当前节点的前驱节点的shouldParkAfterFailedAcquire方法,检查当前节点的前驱节点的waitstatus。shouldParkAfterFailedAcquire方法内部如下:

 1 final boolean acquireQueued(final Node node, int arg) {
 2         boolean failed = true;
 3         try {
 4             boolean interrupted = false;
 5             for (;;) {
 6                 final Node p = node.predecessor();
 7                 if (p == head && tryAcquire(arg)) {
 8                     setHead(node);
 9                     p.next = null; // help GC
10                     failed = false;
11                     return interrupted;
12                 }
13                 if (shouldParkAfterFailedAcquire(p, node) &&
14                     parkAndCheckInterrupt())
15                     interrupted = true;
16             }
17         } finally {
18             if (failed)
19                 cancelAcquire(node);
20         }
21     }

1. 如果前驱节点的waitStatus为-1,也就是SIGNAL,就返回true。

2. 如果当前节点的前驱节点的waitstatus大于0,也就是说被CANCEL掉了,这个时候我们会除掉这个节点。

3. 如果都不是以上的情况,就通过CAS操作将这个前驱节点设置成SIGHNAL。

很明显,我们在这里的情况是第3种情况,并且这个方法运行后返回false。

此时的结构如下,主要是head节点的waitStatus由0变成了-1。

第二次循环:获取我们传入node的前驱节点,判断是否是head节点,现在我们的状态是:

 

很明显满足当前node节点的前驱节点是head节点,那么现在我们就要去调用tryAcquire方法,也就是NonfairSync类的tryAcquire方法,而这个方法又调用了ReentrantLock.Sync.nonfairTryAcquire方法。

很明显此时thread2获取锁是失败的,直接返回false。按照调用流程,现在进入了当前节点的前驱节点的shouldParkAfterFailedAcquire方法,检查当前节点的前驱节点的waitstatus。此时waitstatus为-1,这个方法返回true。shouldParkAfterFailedAcquire返回true后,就会调用parkAndCheckInterrupt方法,直接将当前线程thread2阻塞。仔细看这个方法acquireQueued方法,是无限循环,感觉如果p == head && tryAcquire(arg)条件不满足循环将永远无法结束,在这里,当然不会出现死循环。因为parkAndCheckInterrupt会把当前线程阻塞。分析到这里,我们的thread2线程已经被阻塞了,这个线程不会再继续执行下去了。

(3). 假设现在我们的thread1还没有释放锁,而现在又来了一个线程thread3。

thread3首先调用lock方法获取锁,首先去抢占锁,因为我们知道thread1还没有释放锁,这个时候thread3肯定抢占失败,于是又调用了acquire方法,接着又失败。接着会去调用addWaiter方法,将当前线程thread3封装成node加入到线程阻塞队列的尾部。现在的结构如下:

addWaiter如下:

 1 private Node addWaiter(Node mode) {
 2         Node node = new Node(Thread.currentThread(), mode);
 3         // Try the fast path of enq; backup to full enq on failure
 4         Node pred = tail;
 5         if (pred != null) {
 6             node.prev = pred;
 7             if (compareAndSetTail(pred, node)) {
 8                 pred.next = node;
 9                 return node;
10             }
11         }
12         enq(node);
13         return node;
14     }

第一步:将当前将要去获取锁的线程也就是thread3和独占模式封装为一个node对象。并且我们也知道在当前的执行环境下,线程阻塞队列不是空的,因为thread2获取了锁,thread2已经加入了队列。很明显,这个时候队列的尾部tail节点也不是null,那么将直接进入到if分支。将尾部tail节点赋值给我们传入的node节点的前驱节点。如下:

第二步:通过CAS将我们传递进来的node节点设置成tail节点,并且将新tail节点设置成老tail节点的后继节点。

到此,addWaiter方法执行完毕,接着执行acquireQueued方法。这是一个自循环方法。

 1 final boolean acquireQueued(final Node node, int arg) {
 2         boolean failed = true;
 3         try {
 4             boolean interrupted = false;
 5             for (;;) {
 6                 final Node p = node.predecessor();
 7                 if (p == head && tryAcquire(arg)) {
 8                     setHead(node);
 9                     p.next = null; // help GC
10                     failed = false;
11                     return interrupted;
12                 }
13                 if (shouldParkAfterFailedAcquire(p, node) &&
14                     parkAndCheckInterrupt())
15                     interrupted = true;
16             }
17         } finally {
18             if (failed)
19                 cancelAcquire(node);
20         }
21     }

第一次循环:获取我们传入node的前驱节点,判断是否是head节点,现在我们的状态是:

我们传入node的前驱节点不是head节点,那么直接走第二个if分支,调用shouldParkAfterFailedAcquire方法。

1. 如果前驱节点的waitStatus为-1,也就是SIGNAL,就返回true。

2. 如果当前节点的前驱节点的waitstatus大于0,也就是说被CANCEL掉了,这个时候我们会除掉这个节点。

3. 如果都不是以上的情况,就通过CAS操作将这个前驱节点设置成SIGHNAL。

很明显,我们在这里的情况是第3种情况,并且这个方法运行后返回false。

此时的结构如下,主要是t节点的waitStatus由0变成了-1。

第二次循环:获取我们传入node的前驱节点,判断是否是head节点,现在我们的状态是:

很明显我们传入node的前驱节点不是head节点,那么直接进入shouldParkAfterFailedAcquire方法。

1. 如果前驱节点的waitStatus为-1,也就是SIGNAL,就返回true。

2. 如果当前节点的前驱节点的waitstatus大于0,也就是说被CANCEL掉了,这个时候我们会除掉这个节点。

3. 如果都不是以上的情况,就通过CAS操作将这个前驱节点设置成SIGHNAL。

很明显,我们在这里的情况是第1种情况,并且这个方法运行后返回true。

然后就会调用parkAndCheckInterrupt方法,直接将当前线程thread3阻塞。现在thread2和thread3都已经被阻塞。

 

五、释放锁的过程

现在thread1要开始释放锁了。调用unlock方法,unlock方法又调用了内部的release方法:

1 public final boolean release(int arg) {
2         if (tryRelease(arg)) {
3             Node h = head;
4             if (h != null && h.waitStatus != 0)
5                 unparkSuccessor(h);
6             return true;
7         }
8         return false;
9     }

获取当前AQS的state,并减去1,判断当前线程是否等于AQS的exclusiveOwnerThread,如果不是,就抛异常,这就保证了加锁和释放锁必须是同一个线程。如果(state-1)的结果不为0,说明锁被重入了,需要多次unlock。如果(state-1)等于0,我们就将AQS的ExclusiveOwnerThread设置为null。如果上述操作成功了,也就是tryRelase方法返回了true,那么就会判断当前队列中的head节点,当前结构如下:

如果head节点不为null,并且head节点的waitStatus不为0, 我们就调用unparkSuccessor方法去唤醒head节点的后继节点。

 1 private void unparkSuccessor(Node node) {
 2         /*
 3          * If status is negative (i.e., possibly needing signal) try
 4          * to clear in anticipation of signalling.  It is OK if this
 5          * fails or if status is changed by waiting thread.
 6          */
 7         int ws = node.waitStatus;
 8         if (ws < 0)
 9             compareAndSetWaitStatus(node, ws, 0);
10  
11         /*
12          * Thread to unpark is held in successor, which is normally
13          * just the next node.  But if cancelled or apparently null,
14          * traverse backwards from tail to find the actual
15          * non-cancelled successor.
16          */
17         Node s = node.next;
18         if (s == null || s.waitStatus > 0) {
19             s = null;
20             for (Node t = tail; t != null && t != node; t = t.prev)
21                 if (t.waitStatus <= 0)
22                     s = t;
23         }
24         if (s != null)
25             LockSupport.unpark(s.thread);
26     }

第一步:获取head节点的waitStatus,如果小于0,就通过CAS操作将head节点的waitStatus修改为0,现在是:

第二步:寻找head节点的下一个节点,如果这个节点的waitStatus小于0,就唤醒这个节点,否则遍历下去,找到第一个waitStatus<=0的节点,并唤醒。现在thread2线程被唤醒了,我们知道刚才thread2在acquireQueued被中断,现在继续执行,又进入了for循环,当前节点的前驱节点是head并且调用tryAquire方法获得锁并且成功。那么设置当前Node为head节点,将里面的thead和prev设置为null。

调用完毕后,acquireQueued返回false。并且现在thread2自由了。到此,已经全部分析完毕。

 

原文链接:  https://blog.csdn.net/pfnie/article/details/53191892

 

另附上代码:共4个类 AbstractOwnableSynchronizer、AbstractQueuedSynchronizer、Lock、ReentrantLock,目前仅实现非公平锁部分,如有其他需要请自行扩展

 1 public abstract class AbstractOwnableSynchronizer {
 2     //占有锁的线程
 3     private transient Thread exclusiveOwnerThread;
 4     
 5     protected final void setExclusiveOwnerThread(Thread thread) {
 6         exclusiveOwnerThread = thread;
 7     }
 8     
 9     protected final Thread getExclusiveOwnerThread() {
10         return exclusiveOwnerThread;
11     }
12 }
  1 import java.util.concurrent.locks.LockSupport;
  2 
  3 import sun.misc.Unsafe;
  4 
  5 public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer{
  6     private volatile int state;
  7     private transient volatile Node tail;
  8     private transient volatile Node head;
  9     
 10     private static final Unsafe unsafe = Unsafe.getUnsafe();
 11     private static final long stateOffset;
 12     private static final long tailOffset;
 13     private static final long headOffset;
 14     private static final long waitStatusOffset;
 15     
 16     static {
 17         try {
 18             stateOffset = unsafe.objectFieldOffset
 19                 (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
 20             headOffset = unsafe.objectFieldOffset
 21                 (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
 22             tailOffset = unsafe.objectFieldOffset
 23                 (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
 24             waitStatusOffset = unsafe.objectFieldOffset
 25                 (Node.class.getDeclaredField("waitStatus"));
 26 //            nextOffset = unsafe.objectFieldOffset
 27 //                (Node.class.getDeclaredField("next"));
 28 
 29         } catch (Exception ex) { throw new Error(ex); }
 30     }
 31     
 32     //使用 CAS 实现原子操作
 33     protected final boolean compareAndSetState(int expect, int update) {
 34         return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
 35     }
 36     private final boolean compareAndSetTail(Node expect, Node update) {
 37         return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
 38     }
 39     private final boolean compareAndSetHead(Node update) {
 40         return unsafe.compareAndSwapObject(this, headOffset, null, update);
 41     }
 42     private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {
 43         return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
 44     }
 45     
 46     public final void acquire(int arg) {
 47         if(!tryAcquire(arg)) {
 48             acquireQueued(addWaiter(Node.EXCLUSIVE), arg);
 49         }
 50 //        if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
 51 //            selfInterrupt();
 52 //        }
 53     }
 54     
 55     protected abstract boolean tryAcquire(int arg);
 56     
 57     protected final int getState() {
 58         return state;
 59     }
 60     protected final void setState(int newState) {
 61         state = newState;
 62     }
 63     
 64     static final class Node{
 65         static final Node EXCLUSIVE = null;
 66         Node nextWaiter;
 67         volatile Thread thread;
 68         volatile Node prev;
 69         volatile Node next;
 70         volatile int waitStatus;
 71         
 72         static final int SIGNAL    = -1;
 73         
 74         Node(Thread thread, Node mode) {     // Used by addWaiter
 75             this.nextWaiter = mode;
 76             this.thread = thread;
 77         }
 78         Node(){
 79             
 80         }
 81         
 82         final Node predecessor() throws NullPointerException {
 83             Node p = prev;
 84             if (p == null)
 85                 throw new NullPointerException();
 86             else
 87                 return p;
 88         }
 89     }
 90     
 91     final boolean acquireQueued(final Node node, int arg) {
 92         boolean failed = true;
 93         
 94         boolean interrupted = false;
 95         for (;;) {
 96             final Node p = node.predecessor();
 97             if (p == head && tryAcquire(arg)) {
 98                 setHead(node);
 99                 p.next = null; // help GC
100                 failed = false;
101                 return interrupted;
102             }
103             if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
104                 interrupted = true;
105             }
106         }
107     }
108     private Node addWaiter(Node mode) {
109         Node node = new Node(Thread.currentThread(), mode);
110         // Try the fast path of enq; backup to full enq on failure
111         Node pred = tail;
112         if (pred != null) {
113             node.prev = pred;
114             if (compareAndSetTail(pred, node)) {
115                 pred.next = node;
116                 return node;
117             }
118         }
119         enq(node);
120         return node;
121     }
122     private Node enq(final Node node) {
123         for (;;) {
124             Node t = tail;
125             if (t == null) { // Must initialize
126                 if (compareAndSetHead(new Node()))
127                     tail = head;
128             } else {
129                 node.prev = t;
130                 if (compareAndSetTail(t, node)) {
131                     t.next = node;
132                     return t;
133                 }
134             }
135         }
136     }
137     
138     private void setHead(Node node) {
139         head = node;
140         node.thread = null;
141         node.prev = null;
142     }
143     private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
144         int ws = pred.waitStatus;
145         if (ws == Node.SIGNAL)
146             /*
147              * This node has already set status asking a release
148              * to signal it, so it can safely park.
149              */
150             return true;
151         if (ws > 0) {
152             /*
153              * Predecessor was cancelled. Skip over predecessors and
154              * indicate retry.
155              */
156             do {
157                 node.prev = pred = pred.prev;
158             } while (pred.waitStatus > 0);
159             pred.next = node;
160         } else {
161             /*
162              * waitStatus must be 0 or PROPAGATE.  Indicate that we
163              * need a signal, but don't park yet.  Caller will need to
164              * retry to make sure it cannot acquire before parking.
165              */
166             compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
167         }
168         return false;
169     }
170     private final boolean parkAndCheckInterrupt() {
171         LockSupport.park(this);
172         return Thread.interrupted();
173     }
174     
175     /*********      释放锁        ********/
176     public final boolean release(int arg) {
177         if (tryRelease(arg)) {
178             Node h = head;
179             if (h != null && h.waitStatus != 0) {
180                 unparkSuccessor(h);
181             }
182             return true;
183         }
184         return false;
185     }
186     
187     protected abstract boolean tryRelease(int arg);
188     
189     private void unparkSuccessor(Node node) {
190         /*
191          * If status is negative (i.e., possibly needing signal) try
192          * to clear in anticipation of signalling.  It is OK if this
193          * fails or if status is changed by waiting thread.
194          */
195         int ws = node.waitStatus;
196         if (ws < 0) {
197             compareAndSetWaitStatus(node, ws, 0);
198         }
199 
200         /*
201          * Thread to unpark is held in successor, which is normally
202          * just the next node.  But if cancelled or apparently null,
203          * traverse backwards from tail to find the actual
204          * non-cancelled successor.
205          */
206         Node s = node.next;
207         if (s == null || s.waitStatus > 0) {
208             s = null;
209             for (Node t = tail; t != null && t != node; t = t.prev) {
210                 if (t.waitStatus <= 0) {
211                     s = t;
212                 }
213             }
214         }
215         if (s != null) {
216             LockSupport.unpark(s.thread);
217         }
218     }
219 }
1 //锁接口
2 public interface Lock {
3     //加锁
4     void lock();
5     //解锁
6     void unlock();
7 }
 1 //可重入锁
 2 public class ReentrantLock implements Lock {
 3     //同步器
 4     private final Sync sync;
 5     //可重入锁构造器,默认无参构造器使用非公平锁
 6     public ReentrantLock() {
 7         sync = new NonfairSync();
 8     }
 9     
10     //抽象内部类 -- 同步器,继承 AbstractQueuedSynchronizer
11     abstract static class Sync extends AbstractQueuedSynchronizer{
12         abstract void lock();
13         
14         final boolean nonfairTryAcquire(int acquires) {
15             final Thread current = Thread.currentThread();
16             int c = getState();
17             if (c == 0) {
18                 if (compareAndSetState(0, acquires)) {
19                     setExclusiveOwnerThread(current);
20                     return true;
21                 }
22             }
23             else if (current == getExclusiveOwnerThread()) {
24                 int nextc = c + acquires;
25                 if (nextc < 0) { // overflow
26                     throw new Error("Maximum lock count exceeded");
27                 }
28                 setState(nextc);
29                 return true;
30             }
31             return false;
32         }
33         
34         protected final boolean tryRelease(int releases) {
35             int c = getState() - releases;
36             if (Thread.currentThread() != getExclusiveOwnerThread()) {
37                 throw new IllegalMonitorStateException();
38             }
39             boolean free = false;
40             if (c == 0) {
41                 free = true;
42                 setExclusiveOwnerThread(null);
43             }
44             setState(c);
45             return free;
46         }
47     }
48     
49     //内部类 -- 非公平锁,继承 Sync
50     static final class NonfairSync extends Sync{
51         final void lock() {
52             if(compareAndSetState(0, 1)) {
53                 setExclusiveOwnerThread(Thread.currentThread());
54             }else {
55                 acquire(1);
56             }
57         }
58 
59         @Override
60         protected boolean tryAcquire(int acquires) {
61             return nonfairTryAcquire(acquires);
62         }
63     }
64     @Override
65     public void lock() {
66         sync.lock();
67     }
68 
69     @Override
70     public void unlock() {
71         sync.release(1);
72     }
73 
74 }

 

posted @ 2018-11-17 12:00  将王相  阅读(116)  评论(0)    收藏  举报