【多线程】synchronized关键字详解
synchronized是什么?
java中使用synchronized关键字实现加锁/解锁,来保证多线程对共享资源的访问,防止多个线程同时访问共享资源导致数据问题。
synchronized是重量级锁还是轻量级锁?
java早期版本中synchronized是重量级锁,无论是否发生了锁竞争,都会进行加锁的动作。但是java6之后官方对synchronized进行优化,在没有发生锁竞争时,不会进行加锁的动作,只有发生锁竞争时,才会升级为重量级锁。这就是锁升级。
synchronized锁升级原理
- 锁升级的步骤
- 无锁状态
- 偏向锁
- 轻量级锁
- 重量级锁
- 锁释放
JAVA中32位虚拟机对象头信息分布
无锁状态
锁标志位是01,代表还未执行过
偏向锁
偏向锁:代表锁会偏向于第一个获得他的线程,如果接下来的执行过程中,该锁没有被其他线程获取,则持有偏向锁的线程永远不需要再进行同步
加锁流程:
- 当同步对象第一次被一个线程获取后,虚拟机会将锁标志位设置为 01,偏向模式设置为 1,代表进入偏向锁。同时使用CAS将获取到这个锁的线程ID记录在Mark word中,如果cas操作成功,持有偏向锁的线程每次进入这个相关同步块时,虚拟机都可以不在进行任何同步操作(例如加锁、解锁等)
- 一旦有另一个线程尝试获取这个锁,偏向锁模式宣告结束。根据锁对象目前是否处于被锁状态决定是否撤销偏向,撤销后锁标志位恢复到未锁定或轻量级锁状态。
轻量级锁
轻量级锁:如果一个对象虽然有多线程需要加锁,但是多个线程之间加锁是错开的,并无竞争,那么可以使用轻量级锁来优化。如果没有锁膨胀,轻量级锁就不会和操作系统有交互。
加锁流程:
- 代码进入同步块时,如果此时同步对象没有被锁定 (锁标志位 01),则虚拟机在当前线程创建名为(Lock Record)的锁记录空间,用于存储对象Mark Word的拷贝。
- 虚拟机使用CAS将对象的Mark Word更新为执行Lock Record的指针,更新成功后,所标志为变更为00,表示处于轻量级锁。
- 如果更新失败,则意味着该资源存在其他线程访问,出现了锁竞争。虚拟机首先会检查对象Mark Word是否指向当前线程,如果是,则代表以及拥有了锁,直接进行操作。否则代表多个线程竞争同一个锁,锁膨胀为重量级锁,所标志位变为 10,此时Mark Word中存储的是重量级锁的指针,未获取到锁的线程进入阻塞状态。
锁释放
释放锁的流程:
- 轻量级锁/偏向锁解锁过程也同样通过CAS来操作,如果对象Mark Word仍然指向线程的锁记录,就利用CAS将线程中的Mark Word信息替换回来。
- 替换成功,解锁成功
- 替换失败,说明发生了锁竞争,就要在释放锁的同时,唤醒阻塞的线程。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)