Java 1.5之前,共享变量的互斥访问一般是通过synchronized代码块来实现,synchronizedJava早期只有重量级锁模式,在并发不是很高的环境下性能比较低,并且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();}}
  1. 尝试获取锁:
    通过调用cas来设置state锁状态,如果设置成功则说明线程加锁成功。

  2. 加锁失败的线程添加到AQS等待队列:
    通过自旋cas将线程追加到等待队列的末尾,线程进入阻塞状态,并且等待它的前置节点唤醒它。

Java AQS模型相关推荐

  1. Java并发知识梳理(上):并发优缺点,线程状态转换,Java内存模型,Synchronized,Volatile,final,并发三特性,Lock与AQS,ReetrandLock

    努力的意义,就是,在以后的日子里,放眼望去全是自己喜欢的人和事! 整个系列文章为Java并发专题,一是自己的兴趣,二是,这部分在实际理解上很有难度,另外在面试过程中也是经常被问到.所以在学习过程中,记 ...

  2. Java内存模型终于能讲明白啦,建议收藏!

    作者:zhisheng http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 前提 <深入理解 Java 内存模型>程晓明著 ...

  3. Java AQS论文翻译

    描述 大部分在jdk1.5并发包(java.util.concurrent)中的同步器(锁,屏障等)都是使用一个小型框架基于类AbstractQueuedSynchronizer构建的;这个框架对原子 ...

  4. 深入理解 Java 内存模型(转载)

    摘要: 原创出处 http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 「zhisheng」欢迎转载,保留摘要,谢谢! 0. 前提 &l ...

  5. Java高并发编程(三):Java内存模型

    1 Java内存模型的基础 在并发编程里,需要处理两个问题: 线程之间如何通信 线程之间如何同步. 通信指的是线程之间以何种机制来交换信息.在命令式编程里中,线程之间的通信机制有两种:共享内存和消息传 ...

  6. 深入理解 Java内存模型

    深入理解 Java内存模型 原文地址:http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 本文主要内容有 Java 内存模型的基础.重 ...

  7. blp模型 上读下写_Java高并发编程(三):Java内存模型

    1 Java内存模型的基础 在并发编程里,需要处理两个问题: 线程之间如何通信 线程之间如何同步. 通信指的是线程之间以何种机制来交换信息.在命令式编程里中,线程之间的通信机制有两种:共享内存和消息传 ...

  8. 深入理解 Java 内存模型 JMM

    前提 <深入理解 Java 内存模型>程晓明著,该书在以前看过一遍,现在学的东西越多,感觉那块越重要,于是又再细看一遍,于是便有了下面的读书笔记总结.全书页数虽不多,内容讲得挺深的.细看的 ...

  9. Java 内存模型如何保证多线程安全

    掌握线程安全及多线程问题是我们编写高性能代码的基础,下面将从理论到实践,一层一层的解开. 1. 什么是线程安全? 我们用<java concurrency in practice >中的一 ...

最新文章

  1. python字典一键多值_Python实现字典一个键对应多个值
  2. 面试必考-从URL输入到页面展现到底发生了什么
  3. SLF4j、log4j管理系统日志(Maven)
  4. EventLoop 与Channel 的关联
  5. iisnode默认不支持PUT和DELETE的解决
  6. (2.1)HarmonyOS鸿蒙Ability创建,XML和Java页面布局UI
  7. 【转】ubuntu 12.04 LTS将关闭最大化最小化移动到右上角
  8. 保护你的眼睛,把电脑屏幕由白色改为淡绿
  9. latex中插入eps图片方法与遇到xdvipdfmx:fatal: Image inclusion failed for XXX的错误
  10. oracle查看归档日志是否开启,Oracle 开启归档日志以及关闭归档日志
  11. 微信小程序即时通讯(融云sdk)
  12. 摩拜app显示未能连接到服务器,摩拜单车又现大面积故障?回应称未接到反馈
  13. IE6 Peekaboo(躲躲猫) Bug
  14. Jetpack之LiveData
  15. 只有蓝色www.zcool.com.cn
  16. sql执行顺序及性能优化
  17. Navicat导出数据库表
  18. 25家往昔明星网站“血泪史” 教你如何过冬
  19. DICOM医学图像处理:二零一四▪DICOM专栏一览
  20. 概率论考研笔记(四)

热门文章

  1. Excel指定列 拷贝相同的数据
  2. 恶意代码分析实战 6 OllyDbg
  3. python求导函数公式_python怎么实现函数求导
  4. opencv图像对比度亮度调节
  5. 基于UDS服务的BootLoader架构和刷写流程
  6. MEMS陀螺仪、加速度计和磁强计原理
  7. 教你判断iPhone信号强弱,信号差怎么解决?这三个方法很管用!
  8. CAD显示菜单栏的系统变量
  9. 网络安全学习-DOS命令
  10. MFC 右键删除List Contrl控件行