概览:

AQS(简称)依赖内部维护的一个FIFO(先进先出)队列,可以很好的实现阻塞、同步;volatile修饰的属性state,哪个线程先改变这个状态值,那么这个线程就获得了优先权,可以做任何事(当然这些事肯定是我们预先写好的需要执行的业务代码咯[坏笑]),而其他线程则会被挂起,直到之前的线程执行完才会轮到下一个。 类库中同步工具类(CountDownLatch[闭锁]、Semaphore[信号量])就是依靠内部维护一个类来更改这个state来实现其自身的特性(说到底还是执行某些线程、阻塞一些线程)

代码分析前:

节点Node几个关键的属性:

1、volatile Thread thread;当前节点代表的线程

2、volatile Node next;当前结点的后继节点

3、volatile Node prev;当前结点的前驱节点

4、volatile int waitStatus;当前结点的等待状态

1 CANCELLED(线程取消)

-1 SIGNAL(表示当前节点的后继节点需要运行)

-2 CONDITION(表示当前节点在等待condition,也就是在condition队列中)

-3 PROPAGATE (表示当前场景下后续的acquireShared能够得以执行)

0(表示当前节点在sync队列中,等待着获取锁)

代码分析:

//获取状态
public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}
//该方法由子类去实现(改变state的值)
protected boolean tryAcquire(int arg) {throw new UnsupportedOperationException();}
//为snyc队列添加节点
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;//CAS更新尾节点if (compareAndSetTail(pred, node)) {pred.next = node;return node;}}enq(node);return node;}
//判断有没有释放状态的线程并且尝试获取状态,或者将线程挂起
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);}}

//线程执行完后释放持有的状态
public final boolean release(int arg) {if (tryRelease(arg)) {Node h = head;if (h != null && h.waitStatus != 0)unparkSuccessor(h);return true;}return false;}
//子类实现(改变状态的值)
protected boolean tryRelease(int arg) {throw new UnsupportedOperationException();}
//将头节点的后继节点的线程恢复,这样后继节点就可以继续执行之前的循环,获取状态。
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);}

参考:

http://ifeve.com/introduce-abstractqueuedsynchronizer/

http://www.jianshu.com/p/d8eeb31bee5c

转载于:https://www.cnblogs.com/Non-Tecnology/p/6592387.html

深入分析同步工具类之AbstractQueuedSynchronizer相关推荐

  1. 深入理解同步工具类,看这篇就够了

    大家好,我是陶朱公Boy. 今天跟大家分享一个并发编程领域中的一个知识点--同步工具类. 我将结合一个真实线上案例作为背景来展开讲解这一知识点.给大家讲清楚什么是同步工具类.适合的场景.解决了什么问题 ...

  2. 14、详解java同步工具类CountDownLatch

    这篇文章主要讲解java中一个比较常用的同步工具类CountDownLatch,不管是在工作还是面试中都比较常见.我们将通过案例来进行讲解分析. 一.定义 CountDownLatch的作用很简单,就 ...

  3. Java并发中常用同步工具类

    为什么80%的码农都做不了架构师?>>>    同步工具类可以是任何一个对象,只要它根据其自身的状态来协调线程控制流.阻塞队列(BlockingQueue)可以作为同步工具类,其他类 ...

  4. Java 并发编程之同步工具类闭锁 CountDownLatch

    Java 同步工具类CountDownLatch相当于一个计数器,假设一个方法,等待一个计数器从初始值5变为0,每使用一次countdown()方法,计数器的值减少1,当计数器的值为0时,触发某件事. ...

  5. JAVA同步工具类——CountDownLatch

    闭锁 在学习CountDownLatch之前,让我们先了解一下闭锁的概念. 闭锁是一种同步工具类,可以延迟线程的进度直到其到达终止状态:闭锁的作用相当于一扇门,在闭锁到达结束状态之前,这扇门一直是关闭 ...

  6. java并发基础(二)--- Java监视器模型、并发容器、同步工具类(闭锁、信号量)

    原blog链接:http://www.cnblogs.com/peterxiao/p/6921903.html 总结一下第4.5章的东西. 一.java监视器模式 概念:把对象的所有可变状态都封装起来 ...

  7. Java高并发编程:同步工具类

    内容摘要 这里主要介绍了java5中线程锁技术以外的其他同步工具,首先介绍Semaphore:一个计数信号量.用于控制同时访问资源的线程个数,CyclicBarrier同步辅助类:从字面意思看是路障, ...

  8. java semaphore 等待时间_一个java同步工具类Semaphore的详解

    Semaphore是java并发包里面的一个工具类,我们限制可以访问某些资源的线程数目就可以使用Semaphore了.这篇文章将对Semaphore的概念和使用进行一个详解. 一.概念理解 官方是这样 ...

  9. java线程同步barrier_Java多线程同步工具类之CyclicBarrier

    一.CyclicBarrier使用 CyclicBarrier从字面上可以直接理解为线程运行的屏障,它可以让一组线程执行到一个共同的屏障点时被阻塞,直到最后一个线程执行到指定位置,你设置的执行线程就会 ...

最新文章

  1. 那些逃离互联网大厂的年轻人
  2. C# in depth 阅读笔记-- 委托
  3. 5.3.4 TCP流量控制
  4. [扫盲] Salesforce.com: 业界云计算(Cloud Computing)的主要倡导者之一
  5. SpringBoot中使用log4j进行日志管理
  6. network重启失败原因
  7. linux中的ftp是什么意思,什么是linux的ftp
  8. Android之jni日志如何输出
  9. Controller向View传值方式总结
  10. 剑桥女博士创立情绪识别 AI 公司,帮助自闭症患者理解他人表情
  11. SCPPO(十五):IIS配置文件节点加密
  12. 天猫苛费猛如虎,天猫抽检潜“坑爹”
  13. DVD-Cloner 2021 for mac(DVD光盘刻录工具)
  14. 智能实验室-杀马(Defendio) 4.11.0.790
  15. 小觅双目相机标准彩色版SDK的环境配置
  16. 利用js,HTML,css实现一个简单的指针时钟
  17. 类似于萝卜书摘的书摘app推荐
  18. aruba无线ap认证服务器,Aruba无线AP及AC配置.doc
  19. 【STM32L552ZET6QU】小白入门资料汇总
  20. 【MySQL】--架构简介

热门文章

  1. struts2:表单标签
  2. LAMP 系统性能调优
  3. Delphi 2010 新增功能之: Rtti 单元(5): 获取方法的更多信息
  4. ASP生成静态页面的方法
  5. Libiconv裁剪
  6. 使用tcgetattr函数与tcsetattr函数控制终端-转
  7. html监控服务器状态,HTML5-WebSocket实现对服务器CPU实时监控
  8. mysql rpm 日志_mysql5.1.48-1的src.rpm包安装日志(一)
  9. 蓝桥杯 ADV-201 算法提高 我们的征途是星辰大海
  10. 蓝桥杯 PREV-8 历届试题 买不到的数目