Java AQS模型
在Java 1.5
之前,共享变量的互斥访问一般是通过synchronized
代码块来实现,synchronized
在Java
早期只有重量级锁模式,在并发不是很高的环境下性能比较低,并且synchronized
作为一个非公平锁,可能造成一些线程一直处于饥饿状态,也不支持主动的释放锁。因此从Java 1.5
起引入了Java.util.concurrent
并发包,在concurrent
包中提供了一些实用的工具类来支持Java
并发编程。
Semaphore:用于限制同时执行某个操作的线程数的同步辅助类。
CountDownLatch:用于等待其它线程完成操作的同步辅助类。
CyclicBarrier:一种同步辅助类,允许一组线程互相等待,直到所有线程都达到一个共同的屏障点。
ReentrantLock:可重入的互斥锁,用于控制多个线程对共享资源的访问。
ConcurrentHashMap:线程安全的哈希表,用于高并发环境下的 Map 操作。
CopyOnWriteArrayList:线程安全的列表,适合读多写少的场景。
BlockingQueue:阻塞队列,提供了线程安全的队列操作。
基本概念
在理解AQS
之前,要先了解一下AQS
框架中必要的技术概念:
- 自旋锁
自旋是指当线程获取锁时,如果锁已经被独占,线程不会立即进入阻塞状态,而是会一直尝试去获取锁,直到获取锁成功或者超过尝试次数进入阻塞状态。
线程自旋获取锁成功的依据是通过CAS
返回的值来判断,一般是返回true
表示加锁成功。
自旋锁是一种轻量级锁,相比传统的synchronized
锁,在并发竞争不激烈的情况下,可以避免线程频繁的阻塞和唤醒,减少系统的开销。但是在并发竞争激烈的情况下,自旋会导致线程一直尝试获取锁,浪费大量的CPU
时间,性能可能不及重量级锁。
synchronized经过多个版本的优化,已经引入了轻量级锁(也是一种自旋锁),性能并不差。
- 原子操作
CAS
CAS(compare and swap)
是一种原子操作,它有三个参数: 内存位置(V)、预期原值(A)和新值(B),比较预期值与内存位置(V)的值,如果相等,则将该地址处的值设置为新值(V),否则不做任何操作。
在AQS
中,无锁状态0
,大于0
就说明锁被已经被其他线程持有。当线程去加锁时可以拿着0
去比较内存中的锁状态,如果想等,则将内存中的值加1
,加锁成功;如果不相等,说明已经有其他的线程修改了锁状态值,表示加锁失败。CAS
比较、赋值两个步骤是原子性的。
//自旋例子
for (;;) {Node t = tail;if (t == null) { // Must initializeif (compareAndSetHead(new Node()))tail = head;} else {node.prev = t;//cas 操作if (compareAndSetTail(t, node)) {t.next = node;return t;}}}
AQS类结构
Java AQS (AbstractQueuedSynchronizer)
是Java
并发包中的一个抽象类,它使用一个volatile
变量state
来表示同步的状态(锁是否占用),每次只能一个线程占用这个状态资源进行操作,同时通过一个同步等待队列来管理没有获取到同步状态的线程。
AQS 获取锁流程
AQS
定义了一套加锁、释放锁的流程,继承自AQS
的工具类基本会遵守这套逻辑,如下是加锁逻辑:
// 1.尝试获取锁
if (!tryAcquire()){for(;;){//2.将获取锁失败的线程添加到等待队列acquireQueued();}}
尝试获取锁:
通过调用cas
来设置state
锁状态,如果设置成功则说明线程加锁成功。加锁失败的线程添加到
AQS
等待队列:
通过自旋cas
将线程追加到等待队列的末尾,线程进入阻塞状态,并且等待它的前置节点唤醒它。
Java AQS模型相关推荐
- Java并发知识梳理(上):并发优缺点,线程状态转换,Java内存模型,Synchronized,Volatile,final,并发三特性,Lock与AQS,ReetrandLock
努力的意义,就是,在以后的日子里,放眼望去全是自己喜欢的人和事! 整个系列文章为Java并发专题,一是自己的兴趣,二是,这部分在实际理解上很有难度,另外在面试过程中也是经常被问到.所以在学习过程中,记 ...
- Java内存模型终于能讲明白啦,建议收藏!
作者:zhisheng http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 前提 <深入理解 Java 内存模型>程晓明著 ...
- Java AQS论文翻译
描述 大部分在jdk1.5并发包(java.util.concurrent)中的同步器(锁,屏障等)都是使用一个小型框架基于类AbstractQueuedSynchronizer构建的;这个框架对原子 ...
- 深入理解 Java 内存模型(转载)
摘要: 原创出处 http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 「zhisheng」欢迎转载,保留摘要,谢谢! 0. 前提 &l ...
- Java高并发编程(三):Java内存模型
1 Java内存模型的基础 在并发编程里,需要处理两个问题: 线程之间如何通信 线程之间如何同步. 通信指的是线程之间以何种机制来交换信息.在命令式编程里中,线程之间的通信机制有两种:共享内存和消息传 ...
- 深入理解 Java内存模型
深入理解 Java内存模型 原文地址:http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 本文主要内容有 Java 内存模型的基础.重 ...
- blp模型 上读下写_Java高并发编程(三):Java内存模型
1 Java内存模型的基础 在并发编程里,需要处理两个问题: 线程之间如何通信 线程之间如何同步. 通信指的是线程之间以何种机制来交换信息.在命令式编程里中,线程之间的通信机制有两种:共享内存和消息传 ...
- 深入理解 Java 内存模型 JMM
前提 <深入理解 Java 内存模型>程晓明著,该书在以前看过一遍,现在学的东西越多,感觉那块越重要,于是又再细看一遍,于是便有了下面的读书笔记总结.全书页数虽不多,内容讲得挺深的.细看的 ...
- Java 内存模型如何保证多线程安全
掌握线程安全及多线程问题是我们编写高性能代码的基础,下面将从理论到实践,一层一层的解开. 1. 什么是线程安全? 我们用<java concurrency in practice >中的一 ...
最新文章
- python字典一键多值_Python实现字典一个键对应多个值
- 面试必考-从URL输入到页面展现到底发生了什么
- SLF4j、log4j管理系统日志(Maven)
- EventLoop 与Channel 的关联
- iisnode默认不支持PUT和DELETE的解决
- (2.1)HarmonyOS鸿蒙Ability创建,XML和Java页面布局UI
- 【转】ubuntu 12.04 LTS将关闭最大化最小化移动到右上角
- 保护你的眼睛,把电脑屏幕由白色改为淡绿
- latex中插入eps图片方法与遇到xdvipdfmx:fatal: Image inclusion failed for XXX的错误
- oracle查看归档日志是否开启,Oracle 开启归档日志以及关闭归档日志
- 微信小程序即时通讯(融云sdk)
- 摩拜app显示未能连接到服务器,摩拜单车又现大面积故障?回应称未接到反馈
- IE6 Peekaboo(躲躲猫) Bug
- Jetpack之LiveData
- 只有蓝色www.zcool.com.cn
- sql执行顺序及性能优化
- Navicat导出数据库表
- 25家往昔明星网站“血泪史” 教你如何过冬
- DICOM医学图像处理:二零一四▪DICOM专栏一览
- 概率论考研笔记(四)