java并发包顶层AQS(抽象的队列式的同步器)分析,结合ReentrantLock分析(源码分析)
来源:互联网 发布:淘宝外卖系统繁忙35 编辑:程序博客网 时间:2024/05/22 16:51
package com.kailong.lock;import java.util.ArrayList;import java.util.Collection;import java.util.Date;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.LockSupport;import sun.misc.Unsafe;/** * Created by Administrator on 2017/4/20. * 抽象的队列式的同步器 * 不同的自定义同步器争用共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可, * 至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。 * 自定义同步器实现时主要实现以下几种方法: isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。 tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。 tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。 tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。 tryReleaseShared(int):共享方式。尝试释放资源,成功则返回true,失败则返回false。 同步类在实现时一般都将自定义同步器(sync)定义为内部类,供自己使用;而同步类自己(Mutex)则实现某个接口,对外服务。当然 ,接口的实现要直接依赖sync,它们在语义上也存在某种对应关系!! 而sync只用实现资源state的获取-释放方式tryAcquire-tryRelelase,至于线程的排队、等待、唤醒等, 上层的AQS都已经实现好了,我们不用关心。比如自己实现可重入独占锁 接下来将会分析源码 让大家理解这个过程 */public class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable{ private static final long serialVersionUID = 7373984972572414691L;//序列化id protected AbstractQueuedSynchronizer() { }//无参数改造方法 static final class Node{ /** * 指示节点正在等待共享模式的标记 */ static final Node SHARED = new Node(); /** *指示节点正在等待独占模式的标记 */ static final Node EXCLUSIVE = null; /** *waitStatus值指示线程已取消 */ static final int CANCELLED = 1; /** *waitStatus值表示后续线程需要开启 */ static final int SIGNAL = -1; /** *waitStatus值表示线程正在等待状态 */ static final int CONDITION = -2; /** *值指示下一个acquireShared应无条件地传播 */ static final int PROPAGATE = -3; /** * 等待状态 */ volatile int waitStatus; //前驱 volatile Node prev; //后继 volatile Node next; //线程 volatile Thread thread; //下一个等待 Node nextWaiter; /** * 如果节点在共享模式下等待,则返回true。 * @return */ final boolean isShared() { return nextWaiter == SHARED; } /** * 返回上一个节点,如果为null,则抛出NullPointerException。 *当前辈不能为null时使用。 空检查可以 *被淘汰,但目前是为了帮助虚拟机 * @返回此节点的前身 * @return * @throws NullPointerException */ final Node predecessor() throws NullPointerException { Node p = prev; if (p == null) throw new NullPointerException(); else return p; } Node() { // 用于建立初始头或共享标记 } Node(Thread thread, Node mode) { //Used by addWaiter this.nextWaiter = mode; this.thread = thread; } Node(Thread thread, int waitStatus) { // 按条件使用 this.waitStatus = waitStatus; this.thread = thread; } } private transient volatile Node head; private transient volatile Node tail; private volatile int state; protected final int getState() { return state; } protected final void setState(int newState) { state = newState; } protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); } static final long spinForTimeoutThreshold = 1000L; /** * 此方法用于将node加入队尾 * @param node * @return */ private Node enq(final Node node) { //CAS"自旋",直到成功加入队尾 链表操作 加入节点 分两种情况 一如果链表为空则设置为头结点 否则添加即可 //AtomicInteger.getAndIncrement()函数源码,之前分析的cas机制如此,CAS自旋volatile变量 for (;;) { Node t = tail; if (t == null) { // 必须初始化 if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } } /** * addWaiter()将该线程加入等待队列的尾部,并标记为独占模式; * 此方法用于将当前线程加入到等待队列的队尾,并返回当前线程所在的结点 * @param mode * @return */ private Node addWaiter(Node mode) { // //以给定模式构造结点。mode有两种:EXCLUSIVE(独占)和SHARED(共享) Node node = new Node(Thread.currentThread(), mode); // //尝试快速方式直接放到队尾。 这里只是很简单的链表操作只不过多线程 因此需要用cas机制 Node pred = tail;//头结点 if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) {//利用cas机制修改节点 因为多线程操作 所以利用cas保证线程安全 pred.next = node; return node; } } //上一步失败则通过enq入队。 enq(node); return node; } private void setHead(Node node) { head = node; node.thread = null; node.prev = null; } /** * 此方法用于唤醒等待队列中下一个线程。下面是源码: * @param node */ private void unparkSuccessor(Node node) { int ws = node.waitStatus;//这里,node一般为当前线程所在的结点。 if (ws < 0) compareAndSetWaitStatus(node, ws, 0);//置零当前线程所在的结点状态,允许失败。 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)//从这里可以看出,<=0的结点,都是还有效的结点。 s = t; } if (s != null) LockSupport.unpark(s.thread);//唤醒 } /** * 释放 还是cas机制 一个大的自旋 然后修改即可 */ private void doReleaseShared() { 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 cases unparkSuccessor(h);//唤醒后继 } else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) continue; // loop on failed CAS } if (h == head) // loop if head changed break; } } /** * 此方法在setHead()的基础上多了一步,就是自己苏醒的同时,如果条件符合( * 比如还有剩余资源),还会去唤醒后继结点,毕竟是共享模式! doReleaseShared()我们留着下一小节的releaseShared()里来讲。 * @param node * @param propagate */ private void setHeadAndPropagate(Node node, int propagate) { Node h = head; setHead(node);//head指向自己 //如果还有剩余量,继续唤醒下一个邻居线程 if (propagate > 0 || h == null || h.waitStatus < 0 || (h = head) == null || h.waitStatus < 0) { Node s = node.next; if (s == null || s.isShared()) doReleaseShared(); } } private void cancelAcquire(Node node) { if (node == null) return; node.thread = null; Node pred = node.prev; while (pred.waitStatus > 0) node.prev = pred = pred.prev; Node predNext = pred.next; node.waitStatus = Node.CANCELLED; if (node == tail && compareAndSetTail(node, pred)) { compareAndSetNext(pred, predNext, null); } else { 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 } } private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus;//拿到前驱的状态 if (ws == Node.SIGNAL) return true;// //如果已经告诉前驱拿完号后通知自己一下,那就可以安心休息了 if (ws > 0) { /* 8 * 如果前驱放弃了,那就一直往前找,直到找到最近一个正常等待的状态,并排在它的后边。 9 * 注意:那些放弃的结点,由于被自己“加塞”到它们前边,它们相当于形成一个无引用链,注意垃圾回收 会进行可达性分析,稍后就会被保安大叔赶走了(GC回收)!10 */ do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } else { //如果前驱正常,那就把前驱的状态设置成SIGNAL,告诉它拿完号后通知自己一下。有可能失败, compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; } static void selfInterrupt() { Thread.currentThread().interrupt(); } /** * 如果线程找好安全休息点后,那就可以安心去休息了。此方法就是让线程去休息,真正进入等待状态。 * @return */ private final boolean parkAndCheckInterrupt() { LockSupport.park(this); return Thread.interrupted(); } /** * acquireQueued()使线程在等待队列中获取资源,一直获取到资源后才返回。 * 如果在整个等待过程中被中断过,则返回true,否则返回false。 * 进入等待状态休息,直到其他线程彻底释放资源后唤醒自己,自己再拿到资源,然后就可以去干自己想干的事了 * 在等待队列中排队拿号 * @param node * @param arg * @return */ 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)) {////拿到资源后,将head指向该结点。所以head所指的标杆结点,就是当前获取到资源的那个结点或null。 setHead(node); p.next = null; // help GC 这里帮助垃圾回收器回收节点 failed = false;//返回等待过程中是否被中断过 return interrupted; } // //如果自己可以休息了,就进入waiting状态,直到被unpark() /** * 结点进入队尾后,检查状态,找到安全休息点; 调用park()进入waiting状态,等待unpark()或interrupt()唤醒自己; 被唤醒后,看自己是不是有资格能拿到号。如果拿到,head指向当前结点, 并返回从入队到拿到号的整个过程中是否被中断过;如果没拿到,继续流程1。 */ if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())//检查状态 接下来将会进行检查状态分析 看看线程是否进入waiting状态 interrupted = true;////如果等待过程中被中断过,哪怕只有那么一次,就将interrupted标记为true } } finally { if (failed) cancelAcquire(node); } } 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 GC failed = false; return; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } 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 GC failed = 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); } } /** * 此方法用于将当前线程加入等待队列尾部休息,直到其他线程释放资源唤醒自己, * 自己成功拿到相应量的资源后才返回。下面是doAcquireShared()的源码: * 有木有觉得跟acquireQueued()很相似?对,其实流程并没有太大区别。 * 只不过这里将补中断的selfInterrupt()放到doAcquireShared()里了, * 而独占模式是放到acquireQueued()之外,其实都一样. 跟独占模式比, * 还有一点需要注意的是,这里只有线程是head.next时(“老二”), * 才会去尝试获取资源,有剩余的话还会唤醒之后的队友。那么问题就来了, * 假如老大用完后释放了5个资源,而老二需要6个,老三需要1个,老四需要2个。 * 因为老大先唤醒老二,老二一看资源不够自己用继续park(),也更不会去唤醒老三和老四了。 * 独占模式,同一时刻只有一个线程去执行,这样做未尝不可;但共享模式下, * 多个线程是可以同时执行的,现在因为老二的资源需求量大, * 而把后面量小的老三和老四也都卡住了。 * @param arg */ 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);//如果到head的下一个,因为head是拿到资源的线程,此时node被唤醒, // 很可能是head用完资源来唤醒自己的,尝试获取资源 if (r >= 0) { setHeadAndPropagate(node, r);//将head指向自己,还有剩余资源可以再唤醒之后的线程 p.next = null; // help GC if (interrupted) selfInterrupt();//如果等待过程中被打断过,此时将中断补上。 failed = false; return; } } //判断状态,寻找安全点,进入waiting状态,等着被unpark()或interrupt() if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } 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 GC failed = false; return; } } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } } 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 GC failed = 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); } } /** * tryAcquire()尝试直接去获取资源,如果成功则直接返回; * 此方法尝试去获取独占资源。如果获取成功,则直接返回true,否则直接返回false。 * 这也正是tryLock()的语义,当然不仅仅只限于tryLock()。如下是tryAcquire()的源码: * 至于为甚这里直接抛出异常因为AQS只是一个框架,具体资源的获取/释放方式交由自定义同步器去实现,之所以没有抽象是因为 * 只是抢占锁 该框架还有共享锁的定义 所以写成抽象不方便开发者书写。 * @param arg * @return */ protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); } /** * * @param arg * @return * 跟tryAcquire()一样,这个方法是需要独占模式的自定义同步器去实现的。正常来说,tryRelease()都会成功的,因为这是独占模式,该线程来释放资源,那么它肯定已经拿到独占资源了,直接减掉相应量的资源即可(state-=arg),也不需要考虑线程安全的问题。但要注意它的返回值,上面已经提到了,release()是根据tryRelease()的返回值来判断该线程是否已经完成释放掉资源了!所以自义定同步器在实现时, * 如果已经彻底释放资源(state=0),要返回true,否则返回false 和上面的设计理念一样 * 这个函数并不复杂。一句话概括:用unpark()唤醒等待队列中最前边的那个未放弃线程,这里我们也用s来表示吧。此时,再和acquireQueued()联系起来,s被唤醒后,进入if (p == head && tryAcquire(arg))的判断(即使p!=head也没关系,它会再进入shouldParkAfterFailedAcquire()寻找一个安全点。这里既然s已经是等待队列中最前边的那个未放弃线程了,那么通过shouldParkAfterFailedAcquire()的调整,s也必然会跑到head的next结点,下一次自旋p==head就成立啦),然后s把自己设置成head标杆结点,表示自己已经获取到资源了, * acquire()也返回了!!release()是独占模式下线程释放共享资源的顶层入口。它会释放指定量的资源,如果彻底释放了(即state=0),它会唤醒等待队列里的其他线程来获取资源。 */ protected boolean tryRelease(int arg) { throw new UnsupportedOperationException(); } /** * @param arg * @return */ protected int tryAcquireShared(int arg) { throw new UnsupportedOperationException(); } protected boolean tryReleaseShared(int arg) { throw new UnsupportedOperationException(); } protected boolean isHeldExclusively() { throw new UnsupportedOperationException(); } /** * 此方法是独占模式下线程获取共享资源的顶层入口。如果获取到资源,线程直接返回,否则进入等待队列,直到获取到资源为止,且整个过程忽略中断的影响。这也正是lock()的语义, * 当然不仅仅只限于lock()。获取到资源后,线程就可以去执行其临界区代码了.调用自定义同步器的tryAcquire()尝试直接去获取资源,如果成功则直接返回; 没成功,则addWaiter()将该线程加入等待队列的尾部,并标记为独占模式;acquireQueued()使线程在等待队列中休息,有机会时(轮到自己,会被unpark())会去尝试获取资源。获取到资源后才返回。如果在整个等待过程中被中断过,则返回true,否则返回false。 如果线程在等待过程中被中断过,它是不响应的。只是获取资源后才再进行自我中断selfInterrupt(),将中断补上。 * @param arg */ public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } public final void acquireInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (!tryAcquire(arg)) doAcquireInterruptibly(arg); } public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); return tryAcquire(arg) || doAcquireNanos(arg, nanosTimeout); } /** * 释放 * @param arg * @return */ public final boolean release(int arg) { if (tryRelease(arg)) {//它调用tryRelease()来释放资源。有一点需要注意的是,它是根据tryRelease()的返回值来判断该线程是否已经完成释放掉资源了!所以自定义同步器在设计tryRelease()的时候要明确这一点!! Node h = head;//找到头结点 if (h != null && h.waitStatus != 0) unparkSuccessor(h);//唤醒等待队列里的下一个线程 return true; } return false; } /** * 此方法是共享模式下线程获取共享资源的顶层入口。它会获取指定量的资源,获取成功则直接返回,获取失败则进入等待队列, * 直到获取到资源为止,整个过程忽略中断。下面是acquireShared()的源码:tryAcquireShared()尝试获取资源,成功则直接返回; 失败则通过doAcquireShared()进入等待队列park(),直到被unpark()/interrupt()并成功获取到资源才返回。整个等待过程也是忽略中断的。 其实跟acquire()的流程大同小异,只不过多了个自己拿到资源后,还会去唤醒后继队友的操作(这才是共享嘛)。 * @param arg */ public final void acquireShared(int arg) { /** * 这里tryAcquireShared()依然需要自定义同步器去实现。但是AQS已经把其返回值的语义定义好了: * 负值代表获取失败;0代表获取成功,但没有剩余资源;正数表示获取成功,还有剩余资源,其他线程还可以去获取。 * 所以这里acquireShared()的流程就是:tryAcquireShared()尝试获取资源,成功则直接返回; 失败则通过doAcquireShared()进入等待队列,直到获取到资源为止才返回。 */ if (tryAcquireShared(arg) < 0) doAcquireShared(arg); } public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); } public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); return tryAcquireShared(arg) >= 0 || doAcquireSharedNanos(arg, nanosTimeout); } /** * releaseShared()吧。此方法是共享模式下线程释放共享资源的顶层入口。它会释放指定量的资源, * 如果彻底释放了(即state=0),它会唤醒等待队列里的其他线程来获取资源。下面是releaseShared()的源码: * 释放掉资源后,唤醒后继。跟独占模式下的release()相似,但有一点稍微需要注意: * 独占模式下的tryRelease()在完全释放掉资源(state=0)后,才会返回true去唤醒其他线程, * 这主要是基于可重入的考量;而共享模式下的releaseShared()则没有这种要求, * 一是共享的实质--多线程可并发执行;二是共享模式基本也不会重入, * 所以自定义同步器可以根据需要决定返回值。 * @param arg * @return */ public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) {//尝试释放资源 doReleaseShared();//唤醒后继结点 return true; } return false; } public final boolean hasQueuedThreads() { return head != tail; } public final boolean hasContended() { return head != null; } public final Thread getFirstQueuedThread() { return (head == tail) ? null : fullGetFirstQueuedThread(); } private Thread fullGetFirstQueuedThread() { 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; 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; } 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; } final boolean apparentlyFirstQueuedIsExclusive() { Node h, s; return (h = head) != null && (s = h.next) != null && !s.isShared() && s.thread != null; } public final boolean hasQueuedPredecessors() { Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); } public final int getQueueLength() { int n = 0; for (Node p = tail; p != null; p = p.prev) { if (p.thread != null) ++n; } return n; } 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; } 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; } 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; } public String toString() { int s = getState(); String q = hasQueuedThreads() ? "non" : ""; return super.toString() + "[State = " + s + ", " + q + "empty queue]"; } 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 queue return true; return findNodeFromTail(node); } private boolean findNodeFromTail(Node node) { Node t = tail; for (;;) { if (t == node) return true; if (t == null) return false; t = t.prev; } } final boolean transferForSignal(Node node) { if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) return false; Node p = enq(node); int ws = p.waitStatus; if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) LockSupport.unpark(node.thread); return true; } final boolean transferAfterCancelledWait(Node node) { if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) { enq(node); return true;} while (!isOnSyncQueue(node)) Thread.yield(); return false; } 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; } } public final boolean owns(ConditionObject condition) { return condition.isOwnedBy(this); } public final boolean hasWaiters(ConditionObject condition) { if (!owns(condition)) throw new IllegalArgumentException("Not owner"); return condition.hasWaiters(); } public final int getWaitQueueLength(ConditionObject condition) { if (!owns(condition)) throw new IllegalArgumentException("Not owner"); return condition.getWaitQueueLength(); } public final Collection<Thread> getWaitingThreads(ConditionObject condition) { if (!owns(condition)) throw new IllegalArgumentException("Not owner"); return condition.getWaitingThreads(); } 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; public ConditionObject() { } private Node addConditionWaiter() { Node t = lastWaiter; // If lastWaiter is cancelled, clean out. if (t != null && t.waitStatus != Node.CONDITION) { unlinkCancelledWaiters(); t = lastWaiter; } Node node = new Node(Thread.currentThread(), Node.CONDITION); if (t == null) firstWaiter = node; else t.nextWaiter = node; lastWaiter = node; return node; } private void doSignal(Node first) { do { if ( (firstWaiter = first.nextWaiter) == null) lastWaiter = null; first.nextWaiter = null; } while (!transferForSignal(first) && (first = firstWaiter) != null); } private void doSignalAll(Node first) { lastWaiter = firstWaiter = null; do { Node next = first.nextWaiter; first.nextWaiter = null; transferForSignal(first); first = next; } while (first != null); } 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; else trail.nextWaiter = next; if (next == null) lastWaiter = trail; } else trail = t; t = next; } } public final void signal() { if (!isHeldExclusively()) throw new IllegalMonitorStateException(); Node first = firstWaiter; if (first != null) doSignal(first); } public final void signalAll() { if (!isHeldExclusively()) throw new IllegalMonitorStateException(); Node first = firstWaiter; if (first != null) doSignalAll(first); } 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(); } private static final int REINTERRUPT = 1; private static final int THROW_IE = -1; private int checkInterruptWhileWaiting(Node node) { return Thread.interrupted() ? (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) : 0; } private void reportInterruptAfterWait(int interruptMode) throws InterruptedException { if (interruptMode == THROW_IE) throw new InterruptedException(); else if (interruptMode == REINTERRUPT) selfInterrupt(); } 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 cancelled unlinkCancelledWaiters(); if (interruptMode != 0) reportInterruptAfterWait(interruptMode); } 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(); } 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; } 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; } final boolean isOwnedBy(AbstractQueuedSynchronizer sync) { return sync == AbstractQueuedSynchronizer.this; } 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; } 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; } 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; } } 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 { /** * 利用静态代码块 实现得到对象的偏移量 那么就可一利用cas机制了 */ 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); } } private final boolean compareAndSetHead(Node update) { return unsafe.compareAndSwapObject(this, headOffset, null, update); } private final boolean compareAndSetTail(Node expect, Node update) { return unsafe.compareAndSwapObject(this, tailOffset, expect, update); } private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) { return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update); } private static final boolean compareAndSetNext(Node node, Node expect, Node update) { return unsafe.compareAndSwapObject(node, nextOffset, expect, update); } }
package com.kailong.lock;/** * Created by Administrator on 2017/4/20. */public class AbstractOwnableSynchronizer implements java.io.Serializable { /** 序列化id */ private static final long serialVersionUID = 3737899427754241961L; /** * 空构造器供子类使用。 */ protected AbstractOwnableSynchronizer() { } /** * 当前所有者的排他模式同步。 */ private transient Thread exclusiveOwnerThread; /** * 设置当前拥有独占访问权限的线程。 {@code null}参数表示没有线程拥有访问权限。 这种方法不会强加任何同步或 {@code volatile}字段访问。 @param线程所有者线程 */ protected final void setExclusiveOwnerThread(Thread thread) { exclusiveOwnerThread = thread; } /** *返回由{@code setExclusiveOwnerThread}最后设置的线程, *或{@code null}如果从未设置。 此方法不另行 *强制执行任何同步或{@code易失性}字段访问。 *返回所有者线程 */ protected final Thread getExclusiveOwnerThread() { return exclusiveOwnerThread; }}
package com.kailong.lock;import java.util.Collection;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;import java.util.concurrent.locks.ReentrantReadWriteLock;/** * Created by Administrator on 2017/4/20. */public class MyLock { private final Sync sync;//同步策略 /** * 抽象的同步 用模板方法设计模式 提供两种策略 公平锁和非公平锁 */ static abstract class Sync extends AbstractQueuedSynchronizer{ private static final long serialVersionUID = -5179523762034025860L; abstract void lock();//抽象加锁方法 /** * 这个方法相当于AQS的ryAcquire,为什么非公平版的TryAcquire代码需要写在父类Sync 这里? 注意tryLock,它是只调用非公平版的tryLock。而ReentrantLock 是代理了 Sync ,根据多态机制。所以非公平版的TryAcquire只能写在父类Sync这里了。 * @param acquires * @return */ final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } protected final boolean isHeldExclusively() { return getExclusiveOwnerThread() == Thread.currentThread(); } final ConditionObject newCondition() { return new ConditionObject(); } final Thread getOwner() { return getState() == 0 ? null : getExclusiveOwnerThread(); } final int getHoldCount() { return isHeldExclusively() ? getState() : 0; } final boolean isLocked() { return getState() != 0; } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } } /** * 静态内部类 实现非公平锁 */ static final class NonfairSync extends Sync{ @Override void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } /** * 静态内部类实现公平锁 */ static final class FairSync extends Sync{ @Override void lock() { acquire(1); } protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } } /** * 无参构造方法默认是非公平锁 */ public MyLock() { sync = new NonfairSync(); } /** * 传递boolean值 判断公平锁还是非公平锁 * @param fair */ public MyLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } /** * 加锁方法 调用sync的lock方法 他会根据子类的模板方法来加锁 实现公平锁或者非公平锁 */ public void lock() { sync.lock(); } /** * * @throws InterruptedException */ public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } /** * * @return */ public boolean tryLock() { return sync.nonfairTryAcquire(1); } /** * * @param timeout * @param unit * @return * @throws InterruptedException */ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } /** * */ public void unlock() { sync.release(1); } /** * * @return */ public Condition newCondition() { return sync.newCondition(); } /** * * @return */ public int getHoldCount() { return sync.getHoldCount(); } /** * * @return */ public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } /** * * @return */ public boolean isLocked() { return sync.isLocked(); } /** * * @return */ public final boolean isFair() { return sync instanceof FairSync; } /** * * @return */ protected Thread getOwner() { return sync.getOwner(); } /** * * @return */ public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } /** * * @param thread * @return */ public final boolean hasQueuedThread(Thread thread) { return sync.isQueued(thread); } /** * * @return */ public final int getQueueLength() { return sync.getQueueLength(); } /** * * @return */ protected Collection<Thread> getQueuedThreads() { return sync.getQueuedThreads(); } /** * * @param condition * @return */ public boolean hasWaiters(Condition condition) { if (condition == null) throw new NullPointerException(); if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition); } /** * * @param condition * @return */ public int getWaitQueueLength(Condition condition) { if (condition == null) throw new NullPointerException(); if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition); } /** * * @param condition * @return */ protected Collection<Thread> getWaitingThreads(Condition condition) { if (condition == null) throw new NullPointerException(); if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition); } /** * toString 方法覆盖 * @return */ public String toString() { Thread o = sync.getOwner(); return super.toString() + ((o == null) ? "[Unlocked]" : "[Locked by thread " + o.getName() + "]"); } public static void main(String[]args){ Lock lock=new ReentrantLock(); }}
package com.kailong.lock;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;/** * Created by Administrator on 2017/4/20. * 自定义顶层接口 实现锁的基本功能 */public interface MysLock { /** * 加锁 如果锁已经被占用那么等待 */ void lock(); /** *获得锁但优先响应中断 * @throws InterruptedException */ void lockInterruptibly() throws InterruptedException; /** * 尝试获得锁 如果成功 返回true 失败返回false 此方法不等待,立即返回 * @return */ boolean tryLock(); /** *给定时间尝试获得锁 * @param time * @param unit * @return * @throws InterruptedException */ boolean tryLock(long time, TimeUnit unit) throws InterruptedException; /** * 释放锁 */ void unlock(); /** *条件 * @return */ Condition newCondition();}
0 0
- java并发包顶层AQS(抽象的队列式的同步器)分析,结合ReentrantLock分析(源码分析)
- Java多线程编程-(12)-Java中的队列同步器AQS和ReentrantLock锁原理简要分析
- Java多线程编程-(14)-Java中的队列同步器AQS和ReentrantLock锁原理简要分析
- 深入理解Java并发机制(4)--AQS、ReentrantLock、ReentrantReadWriteLock源码分析
- Java并发-ReentrantLock源码分析
- java并发-ReentrantLock源码分析
- java并发-ReentrantLock源码分析
- Java 并发 ---ReentrantLock源码分析
- ReentrantLock对AQS的使用代码分析
- Java AQS源码分析
- JAVA AQS抽象队列同步器详解
- Java AQS学习-ReentrantLock源代码分析
- java ReentrantLock源码 分析 妥妥的
- java 并发编程-队列同步器AQS了解
- JAVA 并发类(六) ReentrantLock 源码分析
- ReentrantLock实现的源码分析
- java ReentrantLock源码分析
- Java并发同步器AQS
- bzoj 1095: [ZJOI2007]Hide 捉迷藏 动态树分治+堆
- android studio 卡死新坑
- eclipse新建maven多模块工程
- JPA高级映射
- 第9章 基于HTTP的功能追加协议
- java并发包顶层AQS(抽象的队列式的同步器)分析,结合ReentrantLock分析(源码分析)
- 控制 Memory 和 CPU 资源的使用
- 关于caffe2
- Python基础入门(十七)-函数里的参数
- ionic3/ionic2 配置 用ios/android样式
- 【Linux】Linux中Swap与Memory内存简单介绍
- (4.6.23.1)Android之面向切面编程:AOP 与 Aspect简介
- Nginx环境ssl配置+手动生成证书
- redis.conf配置详细解析