前言

本文简要介绍AQS以及其中两个重要概念:stateNode

AQS

抽象队列同步器AQSjava.util.concurrent.locks包下比较核心的类之一,包括AbstractQueuedSynchronizerAbstractQueuedLongSynchronizer两个类,两者分别采用intlong来定义同步状态state

AQSJava中一些常用锁容器的父类,提供了一套模板方法供子类自定义实现,主要职责在于:

  • 同步状态state的维护
  • 等待队列Node维护阻塞线程

同步状态state

state表示同步状态,不同子类使用它来表示不同含义,举例而言:

  • ReentranLock使用state表示持有锁的线程重入次数。当state大于0时,说明锁已被占用,则当前线程添加到等待队列
  • CountDownLatch使用state表示门栓计数。当计数大于0时,线程添加到等待队列;当线程等于0时,唤醒队列中线程
  • Semaphore使用state表示可用的信号量。当state等于0时,表示没有可用的信号量,线程添加到等待队列;线程执行完后,释放信号量,即state+1

通过三个不可重写方法操作state,子类可使用这三个方法:

// volatile 保证线程可见
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) {
// unsafe#cas to update state
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

等待队列Node

AQS通过内置的FIFO队列来存储阻塞线程,队列本质是一个双向链表,初始时headtail都为null,当获取锁失败线程入队时才初始化辅助头节点(懒加载),将headtail都指向它,辅助头节点不存储线程,节点入队通过CASUnsafe实现,1.9开始varHandle取代了Unsafe)保证线程安全。

队列结构图:

抢占和共享模式

通过stateNodeAQS支持了独占和共享两种获取锁模式,子类只需要重写相关的方法就可以实现以独占或共享的方式获取锁。

// 尝试以独占模式获取操作,需要子类实现允许以独占模式获取它
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
// 尝试以独占的方式释放
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
} // 尝试以共享的方式获取操作
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
// 尝试以共享的方式释放
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
} // 判断调用线程是否是独占锁的持有者
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}

子类不需要实现上面所有方法,实现独占或者共享配套的方法即可。独占锁和共享锁举例如下:

独占锁:

  • ReentranLock
  • ReentranWriteReadLock.WriteLock

共享锁:

  • CountDownLatch
  • CyclicBarrier
  • Semaphore
  • ReentranWriteReadLock.ReadLock

独占锁和共享锁如何实现的呢?请看 Java并发之AQS原理解读(二)

Java并发之AQS原理解读(一)的更多相关文章

  1. Java并发之AQS原理解读(三)

    上一篇:Java并发之AQS原理解读(二) 前言 本文从源码角度分析AQS共享锁工作原理,并介绍下使用共享锁的子类如何工作的. 共享锁工作原理 共享锁与独占锁的不同之处在于,获取锁和释放锁成功后,都会 ...

  2. Java并发之AQS原理解读(二)

    上一篇: Java并发之AQS原理解读(一) 前言 本文从源码角度分析AQS独占锁工作原理,并介绍ReentranLock如何应用. 独占锁工作原理 独占锁即每次只有一个线程可以获得同一个锁资源. 获 ...

  3. Java并发之AQS原理剖析

    概述: AbstractQueuedSynchronizer,可以称为抽象队列同步器. AQS有独占模式和共享模式两种: 独占模式: 公平锁: 非公平锁: 共享模式: 数据结构: 基本属性: /** ...

  4. 并发之AQS原理(一) 原理介绍简单使用

    并发之AQS原理(一) 如果说每一个同步的工具各有各的强大,那么这个强大背后是一个相同的动力,它就是AQS. AQS是什么 AQS是指java.util.concurrent.locks包里的Abst ...

  5. 并发之AQS原理(三) 如何保证并发

    并发之AQS原理(三) 如何保证并发 1. 如何保证并发 AbstractQueuedSynchronizer 维护了一个state(代表了共享资源)和一个FIFO线程等待队列(多线程竞争资源被阻塞时 ...

  6. 并发之AQS原理(二) CLH队列与Node解析

    并发之AQS原理(二) CLH队列与Node解析 1.CLH队列与Node节点 就像通常医院看病排队一样,医生一次能看的病人数量有限,那么超出医生看病速度之外的病人就要排队. 一条队列是队列中每一个人 ...

  7. Java并发之AQS详解

    一.概述 谈到并发,不得不谈ReentrantLock:而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)! 类如其名,抽象的队列式的同步器,AQ ...

  8. Java并发之AQS详解(转)

    一.概述 谈到并发,不得不谈ReentrantLock:而谈到ReentrantLock,不得不谈AbstractQueuedSynchronized(AQS)! 类如其名,抽象的队列式的同步器,AQ ...

  9. 【转】Java并发的AQS原理详解

    申明:此篇文章转载自:https://juejin.im/post/5c11d6376fb9a049e82b6253写的真的很棒,感谢老钱的分享. 打通 Java 任督二脉 —— 并发数据结构的基石 ...

随机推荐

  1. 前端基础div(六)

    实例 文档中的一个部分会显示为绿色: <div style="color:#00FF00"> <h3>This is a header</h3> ...

  2. sqldbx配置连接Oracle 12C数据库

    本地开发环境: Windows10 64位.Oracle 12C客户端 32位.sqlDBX (32位) =============================================== ...

  3. Windows下删除顽固文件夹

    参考链接: https://www.cnblogs.com/azbane/p/9808802.html 第一步:修改当前文件夹所有者为管理员 takeown /f * /a /r 第二步:修改管理员权 ...

  4. 编程思想与算法leetcode_二分算法详解

    二分算法通常用于有序序列中查找元素: 有序序列中是否存在满足某条件的元素: 有序序列中第一个满足某条件的元素的位置: 有序序列中最后一个满足某条件的元素的位置. 思路很简单,细节是魔鬼. 二分查找 一 ...

  5. c++ 的父类 new 重载, 子类new 对象的时候会调用父类的operater new

    子类在new 对象的 时候  父类的new 进行了重载,那么会调用父类的operater new() 函数 #include <iostream> #include <string& ...

  6. Android 开发必备的知识点——JVM基础【转】

    image 1.JVM与操作系统的关系 Java Virtual Machine JVM 全称 Java Virtual Machine,也就是我们耳熟能详的 Java 虚拟机.它能识别 .class ...

  7. SaltStack 任意文件读写漏洞(CVE-2020-11652)

    漏洞影响 SaltStack < 2019.2.4 SaltStack < 3000.2 同CVE-2020-11651 poc git clone https://github.com/ ...

  8. GhostScript 沙箱绕过(命令执行)漏洞(CVE-2018-19475)

    影响范围 Ghostscript 9.24之前版本 将POC作为图片上传,执行命令,抓包 POST /index.php HTTP/1.1 Host: target Accept-Encoding: ...

  9. time() 在thinkphp 3.2.3 模板格式化输出

    {$ltime|date="Y-m-d",###}

  10. [.NET大牛之路 006] 了解 Roslyn 编译器

    .NET大牛之路 • 王亮@精致码农 • 2021.07.09 维基百科对编译器的解释是:编译器是一种程序,它将某种编程语言编写的源代码(原始语言)转换成另一种编程语言(目标语言).编译是从源代码(通 ...