synchronized 和 AQS
synchronized
- 三种加锁方式
- 同步代码块
- 修改普通方法
- 修饰静态方法
- 锁升级过程
- 无锁
- 当一个对象被创建之后,还没有线程进入,这个时候对象处于无锁状态
- 偏向锁
- 当锁处于无锁状态时,有一个 线程A 访问同步块并获取锁时,会在对象头和栈帧中的锁记录中记录 线程id,以后该线程在进入和退出同步块时不需要进行 CAS操作 来进行加锁和解锁,只需要简单的测试一下对象头中的 线程id 和当前线程是否一致
- 轻量级锁
- 在偏向锁的基础上,又有另外一个 线程B 进来,这时判断对象头中存储的 线程A 的 id 和 线程B 不一致,就会使用 CAS 竞争锁,并且升级为轻量级锁,会在线程栈中创建一个锁记录(Lock Record),将 Mark Word 复制到锁记录中,然后线程尝试使用 CAS 将对象头的 Mark Word 替换成指向锁记录的指针,如果成功,则当前线程获得锁;失败,表示其他线程竞争锁,当前线程便尝试 CAS 来获取锁
- 重量级锁
- 当线程没有获得轻量级锁时,线程会 CAS 自旋 来获取锁,当一个线程自旋10次之后,仍然未获得锁,那么就会升级成为重量级锁
- 成为重量级锁之后,线程会进入阻塞队列(EntryList),线程不再自旋获取锁,而是由 CPU 进行调度,线程串行执行
- 无锁
AQS (AbstractQueuedSynchronizer)
这个类在 java.util.concurrent.locks (j.u.c.locks) 包下面
AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如我们提到的 ReentrantLock、ReentrantReadWriteLock 等等皆是基于 AQS 的
AQS 核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态;如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制 AQS 是用 CLH 队列(Craig Landin Hagersten、虚拟双向队列、FIFO 队列)锁实现的,即将暂时获取不到锁的线程加入到队列中
为什么要用虚拟双向队列 ?
很明显嘛,假设队列是单向的如:head -> n1 -> n2 -> tail,出队的时候获取 n1 很简单,head.next 就行了,入队就麻烦了,因为是一个 FIFO 队列,后放的元素要放在尾部,要遍历整个链表到 n2,然后 n2.next = n3;n3.next = tail,入队的复杂度就是 O(n) ,而且 tail 也失去他的意义
相反双向链表出队和入队都是 O(1) 时间复杂度,说白了空间换时间
AQS 定义两种资源共享方式
- 独占锁和共享锁
- 独占锁:同一个时刻只能有一个线程访问,无论是读锁还是写锁
- 共享锁:同一个时刻只能有一个写锁,读锁可以有多个可以同一时刻访问
- Exclusive:独占锁
- 只有一个线程能执行,如 ReentrantLock,又可分为公平锁和非公平锁
- 公平锁:按照线程在队列中的排队顺序,先到者先拿到锁
- 非公平锁:当线程要获取锁时,无视队列顺序直接去抢锁,谁抢到就是谁的
- 只有一个线程能执行,如 ReentrantLock,又可分为公平锁和非公平锁
- Share:共享锁
- 多个线程可同时执行,如 CountDownLatch、Semaphore、 CyclicBarrier、ReadWriteLock
- 独占锁和共享锁
AQS 模板方法
- 使用者继承 AbstractQueuedSynchronizer 并重写指定的方法 (重写方法就是对于共享资源 state 的获取和释放)
- 将 AQS 组合在自定义同步组件的实现中,并调用其模板方法,而这些模板方法会调用使用者重写的方法 (钩子方法)
- AQS 使用模板方法模式,自定义同步器时需要重写下面几个 AQS 提供的模板方法:
isHeldExclusively() // 该线程是否正在独占资源,只有用到 condition才需要去实现它
tryAcquire(int) // 独占方式,尝试获取资源,成功则返回 true,失败则返回 false
tryRelease(int) // 独占方式,尝试释放资源,成功则返回 true,失败则返回 false
tryAcquireShared(int) // 共享方式,尝试获取资源,负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源
tryReleaseShared(int) // 共享方式,尝试释放资源,成功则返回 true,失败则返回 false
ReentrantLock 和 ReentrantReadWriteLock 的区别
ReentrantLock
- 实现 Lock 接口
- 独占锁
ReentrantReadWriteLock
- 实现 ReadWriteLock 接口,有 readLock()、writeLock() 两个方法
- 共享锁
公平锁 和 非公平锁 实现的区别
- 公平锁:lock() 和 tryLock() 会直接调用 acquire() 方法
- 非公平锁:lock() 和 tryLock() 会先调用 CAS 尝试获取锁资源,如果获取不到调用 acquire() 方法
synchronized 和 AQS相关推荐
- 【理解向】对于synchronized,CAS,AQS的基础认识模型
文章目录 前言 一.提供给JAVA使用的锁的实现 1.synchronized (1)实现原理 (2)优缺点 2.CAS Unsafe (1)实现原理 (2)优缺点 二.JAVA中的锁工具的一些实现( ...
- java基础-CAS、synchronized和AQS的理解
乐观锁与悲观锁的区别? 悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程 ...
- Java并发之AQS源码分析ReentranLock、ReentrantReadWriteLock、Condition
基于AQS的独享锁和共享锁的源码分析 基本概念说明 锁的基本原理思考 测试环境 实现方案1 实现方案2 独占锁:ReentrantLock源码分析 类依赖和类成员变量说明 加锁过程,入口方法:lock ...
- Java双刃剑之Unsafe类详解
前一段时间在研究juc源码的时候,发现在很多工具类中都调用了一个Unsafe类中的方法,出于好奇就想要研究一下这个类到底有什么作用,于是先查阅了一些资料,一查不要紧,很多资料中对Unsafe的态度都是 ...
- 【非广告,纯干货】这大概是我看过最有温度的面经分享(已收割京东美团技术专家offer)
说明:本文来源于中华石杉架构班学员 dasthinker 同学在拿下美团.京东两家互联网大厂技术专家offer之后的面经总结 简单自我介绍 本⼈是⼯作多年的⼀枚「⽼码农」,对⽐群⾥的年轻朋友们,是有点 ...
- 2019最全BAT资深Java面试题答案合集,建议收藏~
马上进入求职招聘高峰,总结了一份BAT(阿里.百度等)资深Java相关的面试题答案合集给到大家. 该板块的各面试章节,后续会持续迭代更新最新一线互联网公司的面试题目,建议收藏该页面,不定期更新查看~ ...
- 2019死磕java面试题_死磕 java同步系列之开篇
简介 同步系列,这是彤哥想了好久的名字,本来是准备写锁相关的内容,但是java中的CountDownLatch.Semaphore.CyclicBarrier这些类又不属于锁,它们和锁又有很多共同点, ...
- 『辞旧迎新』一个只会写Bug的Coder年终总结
目录 一个小总结 辞旧 迎新 一个小总结 2020 年即将收官,完成了自己的几个小目标:第一:年底前确定了自己心仪的 offer(文末会告诉大家我去了哪儿):第二:公众号粉丝量完成了破千,虽然非常少, ...
- Java 后端技术清单 2023版
后端开发需要掌握的知识,从入门到精通之路 JAVA后端技术清单 文章目录 JAVA后端技术清单 1. 开发环境 2. 基础知识 4. 编码规范及技术博客 5. 动⼿实践 1. 开发环境 JDK: 版本 ...
最新文章
- mysql外键教程_MySQL外键使用详解
- 常用解决方案技术一览
- 在python子程序中、使用关键字_Python 的控制和函数
- php魔术方法__SET __GET
- 表修改语法之列的增删改
- ibatis 高速缓存
- uniapp ajax数据库查询,uniapp小程序登录、数据请求方式
- 零拷贝实现高效的数据传输 -Efficient data transfer through zero copy
- 社会保险的多层次包括哪些?
- 树莓派python gpio 模仿iic_树莓派高级GPIO库,wiringpi2 for python使用笔记(五)i2c读取测试...
- java redis jar_Java使用Redis
- 不是我吹,这款神仙 IDEA 插件你真没用过!
- MATLAB 均值估计函数normfit
- 软件设计师历年真题(链接在文末)
- pytest之.pytest_cache文件夹作用【Pytest中的cache缓存功能】
- 随心所遇,随遇而安。
- python定向爬虫之淘宝商品比价
- 摩克机器人_第三章 摩克都市的一场灾难(上)
- 移动机器人五种坐标系
- 角谷定理python_递归算法实现角谷定理
热门文章
- 【Linux】exec()系列函数——execl(),execlp(),execle()等的区别
- 无影云电脑Linux如何修改密码
- 二十一世纪最性感的职业:数据科学家
- c语言中argc和argv[ ]的作用及用法
- KindEditor 图片上传功能实现
- Struts Tiles 框架概述
- 【HDU4416】Good Article Good sentence【后缀数组】
- 分布式存储系统——HBase
- 搜索之BM25和BM25F模型
- XILINX FPGA OV5640 摄像头驱动(一)