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,又可分为公平锁和非公平锁

        • 公平锁:按照线程在队列中的排队顺序,先到者先拿到锁
        • 非公平锁:当线程要获取锁时,无视队列顺序直接去抢锁,谁抢到就是谁的
    • 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相关推荐

  1. 【理解向】对于synchronized,CAS,AQS的基础认识模型

    文章目录 前言 一.提供给JAVA使用的锁的实现 1.synchronized (1)实现原理 (2)优缺点 2.CAS Unsafe (1)实现原理 (2)优缺点 二.JAVA中的锁工具的一些实现( ...

  2. java基础-CAS、synchronized和AQS的理解

    乐观锁与悲观锁的区别? 悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程 ...

  3. Java并发之AQS源码分析ReentranLock、ReentrantReadWriteLock、Condition

    基于AQS的独享锁和共享锁的源码分析 基本概念说明 锁的基本原理思考 测试环境 实现方案1 实现方案2 独占锁:ReentrantLock源码分析 类依赖和类成员变量说明 加锁过程,入口方法:lock ...

  4. Java双刃剑之Unsafe类详解

    前一段时间在研究juc源码的时候,发现在很多工具类中都调用了一个Unsafe类中的方法,出于好奇就想要研究一下这个类到底有什么作用,于是先查阅了一些资料,一查不要紧,很多资料中对Unsafe的态度都是 ...

  5. 【非广告,纯干货】这大概是我看过最有温度的面经分享(已收割京东美团技术专家offer)

    说明:本文来源于中华石杉架构班学员 dasthinker 同学在拿下美团.京东两家互联网大厂技术专家offer之后的面经总结 简单自我介绍 本⼈是⼯作多年的⼀枚「⽼码农」,对⽐群⾥的年轻朋友们,是有点 ...

  6. 2019最全BAT资深Java面试题答案合集,建议收藏~

    马上进入求职招聘高峰,总结了一份BAT(阿里.百度等)资深Java相关的面试题答案合集给到大家. 该板块的各面试章节,后续会持续迭代更新最新一线互联网公司的面试题目,建议收藏该页面,不定期更新查看~ ...

  7. 2019死磕java面试题_死磕 java同步系列之开篇

    简介 同步系列,这是彤哥想了好久的名字,本来是准备写锁相关的内容,但是java中的CountDownLatch.Semaphore.CyclicBarrier这些类又不属于锁,它们和锁又有很多共同点, ...

  8. 『辞旧迎新』一个只会写Bug的Coder年终总结

    目录 一个小总结 辞旧 迎新 一个小总结 2020 年即将收官,完成了自己的几个小目标:第一:年底前确定了自己心仪的 offer(文末会告诉大家我去了哪儿):第二:公众号粉丝量完成了破千,虽然非常少, ...

  9. Java 后端技术清单 2023版

    后端开发需要掌握的知识,从入门到精通之路 JAVA后端技术清单 文章目录 JAVA后端技术清单 1. 开发环境 2. 基础知识 4. 编码规范及技术博客 5. 动⼿实践 1. 开发环境 JDK: 版本 ...

最新文章

  1. mysql外键教程_MySQL外键使用详解
  2. 常用解决方案技术一览
  3. 在python子程序中、使用关键字_Python 的控制和函数
  4. php魔术方法__SET __GET
  5. 表修改语法之列的增删改
  6. ibatis 高速缓存
  7. uniapp ajax数据库查询,uniapp小程序登录、数据请求方式
  8. 零拷贝实现高效的数据传输 -Efficient data transfer through zero copy
  9. 社会保险的多层次包括哪些?
  10. 树莓派python gpio 模仿iic_树莓派高级GPIO库,wiringpi2 for python使用笔记(五)i2c读取测试...
  11. java redis jar_Java使用Redis
  12. 不是我吹,这款神仙 IDEA 插件你真没用过!
  13. MATLAB 均值估计函数normfit
  14. 软件设计师历年真题(链接在文末)
  15. pytest之.pytest_cache文件夹作用【Pytest中的cache缓存功能】
  16. 随心所遇,随遇而安。
  17. python定向爬虫之淘宝商品比价
  18. 摩克机器人_第三章 摩克都市的一场灾难(上)
  19. 移动机器人五种坐标系
  20. 角谷定理python_递归算法实现角谷定理

热门文章

  1. 【Linux】exec()系列函数——execl(),execlp(),execle()等的区别
  2. 无影云电脑Linux如何修改密码
  3. 二十一世纪最性感的职业:数据科学家
  4. c语言中argc和argv[ ]的作用及用法
  5. KindEditor 图片上传功能实现
  6. Struts Tiles 框架概述
  7. 【HDU4416】Good Article Good sentence【后缀数组】
  8. 分布式存储系统——HBase
  9. 搜索之BM25和BM25F模型
  10. XILINX FPGA OV5640 摄像头驱动(一)