AQS àì夳堔傛蜴生んèń 2022-04-14 03:37 219阅读 0赞 AQS 继承AOS(含独占线程) volatile int state 组合使用 可重写tryAcquire tryRelease tryAcquireShared tryReleaseShared isHeldExclusively 内含Node: 双向链表(同步队列),thread,waitStatus,nextWaiter(构成条件等待队列,用于Condition.signal/signalAll) waitStatus:1(取消,由于等待超时或中断),大于0无效 0 初始化 SIGNAL 常见,会unpark下一个有效Node thread ,(因此一定要排在signal这样的node后面,安全点) CONDITION 当前线程在条件队列上等待 PROPOGATE **final boolean acquireQueued(final Node node, int arg) { boolean failed = true;//标记是否成功拿到资源 try { boolean interrupted = false;//标记等待过程中是否被中断过 //又是一个“自旋”! for (;;) { final Node p = node.predecessor();//拿到前驱 //如果前驱是head,即该结点已成老二,那么便有资格去尝试获取资源(可能是老大释放完资源唤醒自己的,当然也可能被interrupt了)。 if (p == head && tryAcquire(arg)) { setHead(node);//拿到资源后,将head指向该结点。所以head所指的标杆结点,就是当前获取到资源的那个结点或null。 p.next = null; // setHead中node.prev已置为null,此处再将head.next置为null,就是为了方便GC回收以前的head结点。也就意味着之前拿完资源的结点出队了! failed = false; return interrupted;//返回等待过程中是否被中断过 } //如果自己可以休息了,就进入waiting状态,直到被unpark() if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true;//如果等待过程中被中断过,哪怕只有那么一次,就将interrupted标记为true } } finally { if (failed) cancelAcquire(node); } }** **private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus;//拿到前驱的状态 if (ws == Node.SIGNAL) //如果已经告诉前驱拿完号后通知自己一下,那就可以安心休息了 return true; if (ws > 0) { /* * 如果前驱放弃了,那就一直往前找,直到找到最近一个正常等待的状态,并排在它的后边。 * 注意:那些放弃的结点,由于被自己“加塞”到它们前边,它们相当于形成一个无引用链,稍后就会被保安大叔赶走了(GC回收)! */ do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } else { //如果前驱正常,那就把前驱的状态设置成SIGNAL,告诉它拿完号后通知自己一下。有可能失败,人家说不定刚刚释放完呢! compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; }** ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tvYmV4emY_size_16_color_FFFFFF_t_70] private void unparkSuccessor(Node node) { //这里,node一般为当前线程所在的结点。 int ws = node.waitStatus; if (ws < 0)//置零当前线程所在的结点状态,允许失败。 compareAndSetWaitStatus(node, ws, 0); Node s = node.next;//找到下一个需要唤醒的结点s 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);//唤醒 } [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2tvYmV4emY_size_16_color_FFFFFF_t_70]: /images/20220414/7961317c9f9b4df288ea202717f6e31b.png
相关 AQS详解 前言:之前AQS、ReentrantLock、CountLatchDown大概原理都看懂了,面试的时候一问能说个大概,感觉这样也就行了,跟背课文一样背源码也没什么意思,但是根据 今天药忘吃喽~/ 2022年12月11日 15:29/ 0 赞/ 176 阅读
相关 AQS ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ub 骑猪看日落/ 2022年12月07日 01:53/ 0 赞/ 155 阅读
相关 AQS 1 AQS抽象的队列同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock/Semaphore/CountD ﹏ヽ暗。殇╰゛Y/ 2022年11月09日 03:55/ 0 赞/ 182 阅读
相关 AQS简介 AQS简介 > AQS,AbstractQueuedSynchronizer,即队列同步器 > AQS即是AbstractQueuedSynchronizer,一个用 末蓝、/ 2022年05月25日 00:16/ 0 赞/ 184 阅读
相关 aqs学习 aqs是一个很重要的并发框架,熟悉之后可以很方便的构造自己的并发工具。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text 「爱情、让人受尽委屈。」/ 2022年04月24日 13:24/ 0 赞/ 181 阅读
相关 AQS AQS 继承AOS(含独占线程) volatile int state 组合使用 可重写tryAcquire tryRelease tryAcquireShared tryR àì夳堔傛蜴生んèń/ 2022年04月14日 03:37/ 0 赞/ 220 阅读
相关 AQS详解 AQS的介绍 AQS的全称为(AbstractQueuedSynchronizer),这个类在java.util.concurrent.locks包下面。 ![在这里插 电玩女神/ 2022年02月28日 11:20/ 0 赞/ 284 阅读
相关 AQS笔记 AQS笔记 概述 AQS 是 `AbstractQueueSynchronized` 抽象同步队列的简称,它是实现同步器的基础组件,并发包中锁的底层就是使 我不是女神ヾ/ 2022年02月21日 15:36/ 0 赞/ 204 阅读
相关 AQS架构 AQS,全称是AbstractQueuedSynchronizer,中文译为抽象队列式同步器 AQS架构: ![watermark_type_ZmFuZ3poZW5 水深无声/ 2021年12月10日 01:07/ 0 赞/ 301 阅读
还没有评论,来说两句吧...