当前位置: 首页 > news >正文

Java EE初阶启程记12---synchronized 原理

 🔥个人主页:寻星探路

🎬作者简介:Java研发方向学习者

📖个人专栏: 、《

⭐️人生格言:没有人生来就会编程,但我生来倔强!!!



目录

一、基本特点

二、加锁工作过程

1、偏向锁

2、轻量级锁

3、重量级锁

三、其他的优化操作

1、锁消除

2、锁粗化

四、相关面试题

1、什么是偏向锁?

2、synchronized 实现原理是什么?


一、基本特点

结合上面的锁策略,我们就可以总结出,synchronized具有以下特性(只考虑JDK1.8):

1)开始时是乐观锁,如果锁冲突频繁,就转换为悲观锁。

2)开始是轻量级锁实现,如果锁被持有的时间较长,就转换成重量级锁。

3)实现轻量级锁的时候大概率用到的自旋锁策略。

4)是一种不公平锁。

5)是一种可重入锁。

6)不是读写锁。

二、加锁工作过程

        JVM 将 synchronized 锁分为无锁、偏向锁、轻量级锁、重量级锁状态。会根据情况,进行依次升级。

1、偏向锁

第一个尝试加锁的线程,优先进入偏向锁状态。

偏向锁不是真的"加锁",只是给对象头中做一个"偏向锁的标记",记录这个锁属于哪个线程。

如果后续没有其他线程来竞争该锁,那么就不用进行其他同步操作了(避免了加锁解锁的开销)

如果后续有其他线程来竞争该锁(刚才已经在锁对象中记录了当前锁属于哪个线程了,很容易识别当前申请锁的线程是不是之前记录的线程),那就取消原来的偏向锁状态,进入一般的轻量级锁状态。

偏向锁本质上相当于"延迟加锁",能不加锁就不加锁,尽量来避免不必要的加锁开销。

但是该做的标记还是得做的,否则无法区分何时需要真正加锁。

举个例子理解偏向锁:

假设男主是一个锁,女主是一个线程,如果只有这一个线程来使用这个锁,那么男主女主即使不领证结婚(避免了高成本操作),也可以一直幸福的生活下去。

但是女配出现了,也尝试竞争男主,此时不管领证结婚这个操作成本多高,女主也势必要把这个动作完成了,让女配死心。

2、轻量级锁

随着其他线程进入竞争,偏向锁状态被消除,进入轻量级锁状态(自适应的自旋锁)。

此处的轻量级锁就是通过CAS来实现。

        通过CAS检查并更新一块内存(比如null=>该线程引用)。

        如果更新成功,则认为加锁成功。

        如果更新失败,则认为锁被占用,继续自旋式的等待(并不放弃CPU)。

自旋操作是一直让CPU空转,比较浪费CPU资源。

因此此处的自旋不会一直持续进行,而是达到一定的时间/重试次数,就不再自旋了。

也就是所谓的"自适应"。

3、重量级锁

如果竞争进一步激烈,自旋不能快速获取到锁状态,就会膨胀为重量级锁

此处的重量级锁就是指用到内核提供的mutex。

        执行加锁操作,先进入内核态。

        在内核态判定当前锁是否已经被占用。

        如果该锁没有占用,则加锁成功,并切换回用户态。

        如果该锁被占用,则加锁失败。此时线程进入锁的等待队列,挂起,等待被操作系统唤醒。

        经历了一系列的沧海桑田,这个锁被其他线程释放了,操作系统也想起了这个挂起的线程,于是唤醒这个线程,尝试重新获取锁。

三、其他的优化操作

1、锁消除

编译器+JVM判断锁是否可消除,如果可以,就直接消除。

什么是"锁消除"?

有些应用程序的代码中,用到了synchronized,但其实没有在多线程环境下。(例如StringBuffer)

 StringBuffer sb = new StringBuffer();sb.append("a");sb.append("b");sb.append("c");sb.append("d");

此时每个append的调用都会涉及加锁和解锁,但如果只是在单线程中执行这个代码,那么这些加锁解锁操作是没有必要的,白白浪费了一些资源开销。

2、锁粗化

一段逻辑中如果出现多次加锁解锁,编译器+JVM会自动进行锁的粗化。

锁的粒度:粗和细

实际开发过程中,使用细粒度锁,是期望释放锁的时候其他线程能使用锁。

但是实际上可能并没有其他线程来抢占这个锁,这种情况JVM就会自动把锁粗化,避免频繁申请释放锁。

举个例子理解锁粗化:

滑稽老哥当了领导,给下属交代工作任务:

方式一:

        打电话,交代任务1,挂电话。

        打电话,交代任务2,挂电话。

        打电话,交代任务3,挂电话。

方式二:

        打电话,交代任务1,任务2,任务3,挂电话。

显然,方式⼆是更高效的方案。

可以看到,synchronized的策略是比价复杂的,在背后做了很多事情,目的为了让程序猿哪怕啥都不懂,也不至于写出特别慢的程序。

JVM开发者为了Java程序猿操碎了心。

四、相关面试题

1、什么是偏向锁?

偏向锁不是真的加锁,而只是在锁的对象头中记录一个标记(记录该锁所属的线程)。如果没有其他线程参与竞争锁,那么就不会真正执行加锁操作,从而降低程序开销,一旦真的涉及到其他的线程竞争,再取消偏向锁状态,进入轻量级锁状态。

2、synchronized 实现原理是什么?

参考上面的 synchronized 原理章节全部内容

http://www.dtcms.com/a/449570.html

相关文章:

  • 设计模式简要介绍
  • Python 数据结构综合速查:列表 / 字典 / 集合 / 元组对比
  • 宁波建设工程报名网站搭建一个网站的具体步骤
  • 第十七章:遍历万象,步步为营——Iterator的迭代艺术
  • 记一次vcenter server 无法同步主机的故障处理过程
  • 手搓20颗芯片|专栏开篇:从0到1搭建芯片设计与UVM验证体系
  • 《 Linux 点滴漫谈: 三 》Linux 的骨架:文件系统与目录结构的完整图谱
  • 跨境自建站模板库存网站建设公司
  • 【Web安全】转义字符注入?转义也会失效的SQL注入
  • 虚拟机中建设iis网站网站推广洛阳
  • python+vue高校新生报到管理系统设计(源码+文档+调试+基础修改+答疑)
  • 中秋连连看小游戏开发完整教程
  • 产品图案设计网站一起做网店网站入驻收费
  • traffic-filter inbound acl 概念及题目
  • Python3 XML 解析
  • 驾驭涌现的艺术:自组织系统——解锁复杂世界的创新与适应力
  • 青岛做外贸网站建设西安网站建设培训中心
  • 【MES架构师与C#高级工程师(设备控制方向)两大职业路径的技术】
  • MySQL 8.0.26崩溃恢复全解析
  • 北京哪个网站最好湖南网络营销
  • 【Linux】MobaXterm 工具介绍
  • 2025-10-6学习笔记
  • 【面板数据】各国数字服务贸易进出口额数据集(2005-2023年)
  • dede怎么做商城网站个人网站免费制作平台
  • Oracle OCP认证考试题目详解082系列第57题
  • 嵌入式开发学习日志36——stm32之USART串口通信前述
  • Linux中capability权能管理的实现
  • Python 语法与注释详解
  • joomla 网站建设教程合肥网站推广公司
  • 介绍一个做美食的网站网店网站技术方案