2019独角兽企业重金招聘Python工程师标准>>>

AQS是JUC当中最核心的部分,大部分多线程讲解,都不会详细讲AQS,AQS的源代码,要看明白还是有点困难的。但是一旦看明白了,结构还是蛮清晰的。这里我们把AQS拆开,分成几部分来讲,就会很清楚了。首先先从内部类Nde讲起

上源代码:

static final class Node {static final int CANCELLED =  1;static final int SIGNAL    = -1;static final int CONDITION = -2;static final Node SHARED = new Node();static final Node EXCLUSIVE = null;volatile int waitStatus;volatile Node prev;volatile Node next;volatile Thread thread;Node nextWaiter;final boolean isShared() {return nextWaiter == SHARED;}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;}}

这个NODE类是java.util.concurrent.locks.AbstractQueuedSynchronizer的内部类。主要实现了一个链表的数据结构中的节点。先不谈这个链表是做什么的,我们先看看这个节点是怎么构造的。

首先,这个节点有四个状态 ,其中三在Node类中已经明确定义,另外一个状态为初始状态,值为0

        static final int CANCELLED =  1;static final int SIGNAL    = -1;static final int CONDITION = -2;

1 :当前节点被取消或者中断

-1:下一个节点需要被释放

-2:当前节点正处在等待队列中

0 :不属于任何一种

其次,这个节点有两种模式,其中SHARED是共享模式,EXCLUSIVE是独占模式。

        static final Node SHARED = new Node();static final Node EXCLUSIVE = null;

等一下再介绍这两个模式。先把数据结构看完。

然后是成员变量:

        volatile int waitStatus;volatile Node prev;volatile Node next;volatile Thread thread;Node nextWaiter;

volatile int waitStatus:当前节点的状态,一共四种

volatile Node prev:链表的前一个节点

volatile Node next:链表的后一个节点

volatile Thread thread:这个节点所处的线程

Node nextWaiter:这个节点等待的模式(共享模式和独占模式)

接下去的两个方法和三个构造方法非常简单,就不讲了。


问题1:这个链表是如何工作的?

用一张图表示队列的工作方式:

  1. 每个节点都拥有一个指针,知道自己的前一个节点

  2. 每个节点都有一个状态位,表示是否占用资源

  3. 每个节点都要完成自旋判断上一个节点的状态(图中while循环),才能真正的执行自己的逻辑

  4. 当逻辑执行完,会修改自己的节点的状态,放开下个节点的自旋

  5. 新插入的节点,永远在队尾

上图已经非常清楚的描述了这个队列的工作方式。这就是CLH锁的原理。其实实现锁还有几种不同的方式。(点击了解更多锁的实现原理和比较)

由于一个线程的状态不止两种,所以Node的状态实现,并没有用True/False表示。而是用了waitStatus表示。另外为了操作的方便,Node并没有使用单向链表,而是双向链表。这样操作起来会方便很多。

如下图:

  1. 每个节点都拥有一个指针,知道自己的前一个节点和后一个节点

  2. 每个节点都有一个状态位,表示是否占用资源

  3. 每个节点都要完成自旋判断上一个节点的状态(图中while循环),才能真正的执行自己的逻辑

  4. 当逻辑执行完,会修改自己的节点的状态,放开下个节点的自旋

  5. 新插入的节点,永远在队尾。队尾节点标记新插入节点

  6. 被取消或者中断的线程节点,会从链表中断开,被删除

还记得在讲LockSupport(点击查看源码)中是如何挂起和恢复一个线程的吗?Thread对象就是做这个的。

到此为止,我们的图与Node类的结构是不是已经很像了呢?

问题2:共享模式和独占模式

共享模式和独占模式是两种不同的锁定资源的方式。

最经典的举例就是对共享文件的操作。当第一个,第二个用户都请求读取文件内容时,并不会阻塞用户的读取行为,并且可以并发的读取。

但是当第三个用户请求修改的时候,就会获取一个独占锁。一旦获取了独占锁,所有共享锁的获取或者独占锁的获取都会被阻塞,一直等

到独占锁被释放才会解除阻塞。

实际在JUC中读写锁也是一个很典型的共享与独占的例子。

转载于:https://my.oschina.net/readjava/blog/282969

j.u.c.locks.AbstractQueuedSynchronizer.Node相关推荐

  1. Java-java.util.concurrent.locks.AbstractQueuedSynchronizer

    这个类简称AQS,如果我们要实现的功能是有获取和释放这两个操作,并且获取操作总是能够阻塞,那么我们就应该创建一个锁,并且这个锁继承AbstractQueuedSynchronizer,因为无论是获取, ...

  2. java并发编程——九 AbstractQueuedSynchronizer AQS详解

    文章目录 AbstractQueuedSynchronizer概述 AbstractQueuedSynchronizer的使用 AQS实现分析 同步队列 独占锁的获取与释放 独占式超时获取 共享式锁的 ...

  3. JVM crash at ForUtil.readBlock

    今天同学让帮忙看下JVM错误日志,才发现已经开始接触java3个月,还没看到相关错误日志.平时看的都只是程序运行时写入的日志,关于JVM的错误日志还真没看过.网上收集资料,整理如下. 一.日志文件: ...

  4. Java多线程(五) —— 线程并发库之锁机制

    参考文献: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html 一.Lock与ReentrantLock 前面的章节主要谈谈原子操作 ...

  5. java性能检测工具_Java自带的性能监测工具之jmap

    本文继续介绍Java自带的性能监测工具,本文使用jmap工具来玩~ jmap (Java Memory Map) 命令可以生成Java应用程序的堆快照和对象统计信息,对生成的堆快照进行分析,可以分析堆 ...

  6. 关于springmvc的helloworld的压测报告

    都说hello world 很简单,应该能承受很大的请求压力,那么到底有多大?你知道吗?如果知道,那咱们就不继续了.如果不知道,我们来看一下! 1. 准备工作,快速建立一个基于springmvc的he ...

  7. java 类加载过程

    1. 使用命令行查看类加载过程,在eclipse测试类的run configuration中配置-verbose:class或者-verbose,如下图所示: 运行结果如下所示: [Opened D: ...

  8. JVM -verbose参数详解(转)

    转自:http://www.javaranger.com/archives/367 java -verbose[:class|gc|jni] 在输出设备上显示虚拟机运行信息. 1.java -verb ...

  9. Java虚拟机:深入详细分析Java ClassLoader原理与源码

    一.什么是ClassLoader? ClassLoader就是类加载器,当我们写好一个Java程序之后,都是由若干个.class文件组成的一个完整的Java应用程序,当程序在运行时,即会调用该程序的一 ...

最新文章

  1. MQTT消息长度限制
  2. Android适配难题全面总结
  3. 《C++ primer》--第10章
  4. linux中ftp的用法,linux中的ftp命令用法(7页)-原创力文档
  5. 一个判断射线和三角形相交的函数
  6. java-web的mybatis的学习
  7. Oier's little dream
  8. cs寄存器 x86 特权模式_Windows操作系统管理进程和线程:内核模式和用户模式
  9. 检查硬件变化的命令kudzu
  10. Dynamics CRM 2013 installation
  11. Leetcode 279 完美平方数
  12. 21. 面向服务的体系架构(SOA)
  13. h5前端开发,96道前端面试题
  14. 基于SSM+SpringBoot+Thymeleaf+LayUI的高校大学生成绩分析管理系统(附论文)
  15. 2017计算机知识竞赛题,2017网络安全知识竞赛题库(中学组)word版
  16. 20221106EXCEL/腾讯文档 部分常用函数嵌套用法总结
  17. 《动物世界》电影 观后感
  18. html5手机端页面缩放问题的解决
  19. Generating Event Causality Hypotheses through Semantic Relation
  20. 大数据:Hadoop集群测试

热门文章

  1. php函数serialize()与unserialize()
  2. libevent源码深度剖析
  3. 将文本随意插入网页表单的 textarea
  4. 如何实现可以带详细表格的DropDownList
  5. 一种解决启动进程传递参数过长的方法
  6. 正则表达式简介及在C++11中的简单使用
  7. linux驱动:音频驱动(七)交叉编译alsa库及工具集alsa-utils
  8. java for循环返回值_Java中的for循环——通过示例学习Java编程(9)
  9. ubuntu mysql emma_Ubuntu 11.10 MySQL客户端 Emma 6.0 中文乱码解决办法
  10. python http接口_python处理http接口请求