简述Java中synchronized关键字的底层工作原理

在Java中,synchronized 关键字是一个重要的同步机制,用于控制多线程对共享资源的访问,以防止并发问题。了解 synchronized 的底层工作原理,可以帮助我们更好地编写线程安全的代码。synchronized 关键字可以应用于方法或者代码块,其底层实现依赖于Java虚拟机(JVM)中的监视器锁(Monitor Lock)或内部锁。

1. 锁的获取和释放

当线程进入一个 synchronized 方法或代码块时,它会自动获取锁。当线程离开 synchronized 方法或代码块时,无论是通过正常路径返回还是通过抛出异常,它都会自动释放锁。

2. 锁的类型

  • 轻量级锁:当没有竞争出现时,JVM会使用轻量级锁。这种锁利用CAS(比较并交换)操作,试图不暂停持有锁的线程的执行,而是通过在对象头上的标记字段中记录锁的状态来实现。
  • 重量级锁:当锁竞争激烈时,轻量级锁会升级为重量级锁。这种锁会使其他试图进入同步代码块的线程进入阻塞状态。

3. 对象头和锁状态

Java对象在内存中有一个对象头部,其中包含了锁的信息。根据锁的状态,对象头部的标记字段会有不同的设置:

  • 无锁状态:没有线程持有锁。
  • 偏向锁:一种优化手段,偏向第一个获取它的线程,进入同步块时不需要真正的竞争锁。
  • 轻量级锁:在无实际竞争的情况下使用CAS设置锁定状态。
  • 重量级锁:当有多个线程竞争同一个锁时,锁会升级到重量级锁,相关线程可能会被挂起。

4. 锁的升级过程

  • 初始状态是无锁。
  • 当第一个线程访问同步块时,锁可以升级为偏向锁。
  • 如果另一个线程尝试访问同步块,偏向锁可以脱离偏向模式并升级为轻量级锁。
  • 如果竞争加剧,轻量级锁会升级为重量级锁。

5. 监视器锁和等待/通知机制

JVM内部使用监视器锁来实现 synchronized。监视器锁包含两个队列:等待队列和阻塞队列。等待队列用于存放调用了wait()方法的线程,阻塞队列用于存放尝试获取锁但未成功的线程。当锁被释放时,来自阻塞队列的线程将有机会获取锁,而来自等待队列的线程则需要等到特定条件满足并收到notify()notifyAll()调用。

总结

synchronized 的底层实现复杂且高效,通过锁的不同状态和锁升级机制,JVM可以在运行时根据具体情况调整同步策略,从而提供良好的性能和线程安全保障。

相关推荐
m0_516484672 分钟前
C#winform多选框代码
开发语言·c#
啾啾Fun23 分钟前
Java反射操作百倍性能优化
java·性能优化·反射·缓存思想
20岁30年经验的码农30 分钟前
若依微服务Openfeign接口调用超时问题
java·微服务·架构
曲莫终39 分钟前
SpEl表达式之强大的集合选择(Collection Selection)和集合投影(Collection Projection)
java·spring boot·spring
ajassi20001 小时前
开源 java android app 开发(十二)封库.aar
android·java·linux·开源
q567315231 小时前
Java使用Selenium反爬虫优化方案
java·开发语言·分布式·爬虫·selenium
kaikaile19951 小时前
解密Spring Boot:深入理解条件装配与条件注解
java·spring boot·spring
守护者1701 小时前
JAVA学习-练习试用Java实现“一个词频统计工具 :读取文本文件,统计并输出每个单词的频率”
java·学习
bing_1582 小时前
Spring Boot 中ConditionalOnClass、ConditionalOnMissingBean 注解详解
java·spring boot·后端
ergdfhgerty2 小时前
斐讯N1部署Armbian与CasaOS实现远程存储管理
java·docker