Java全栈面试宝典:锁机制与Spring生命周期深度解析
目录
一、synchronized锁状态机全解析
🔥 问题5:synchronized四态转换与性能对比
锁状态转换流程图
锁特性对比表
CAS操作示例
二、ReentrantLock与synchronized深度对比
🔥 问题6:两大锁机制对比
核心差异矩阵
生产级ReentrantLock示例
三、Spring Bean生命周期与装配机制
🌟 Bean生命周期关键方法
生命周期流程图
关键方法重载示例
🌟 Spring集合注入与自动装配
集合注入示例
自动装配模式对比
四、高频面试题强化训练
1. 如何选择synchronized和ReentrantLock?
2. Bean生命周期回调执行顺序?
3. 自动装配的歧义性如何解决?
一、synchronized锁状态机全解析
🔥 问题5:synchronized四态转换与性能对比
锁状态转换流程图
锁特性对比表
| 锁类型 | 优点 | 缺点 | 适用场景 | JVM参数 |
|---|---|---|---|---|
| 偏向锁 | 无CAS开销,单线程零成本 | 撤销需要暂停线程 | 单线程独占场景 | -XX:+UseBiasedLocking |
| 轻量级锁 | 线程不阻塞,响应快 | 自旋消耗CPU | 低竞争短同步 | 默认启用 |
| 重量级锁 | 不消耗CPU | 线程切换开销大 | 高竞争长同步 | 默认启用 |
CAS操作示例
// 轻量级锁获取伪代码
void enterLightweightLock() {
MarkWord mark = object.markWord;
if (mark.isNeutral()) { // 无锁状态
LockRecord lockRecord = thread.stack.createLockRecord();
lockRecord.displacedHeader = mark;
if (CAS(object.markWord, mark, lockRecord.address)) {
return; // 获取成功
}
}
// 升级为重量级锁
inflateLock();
}
二、ReentrantLock与synchronized深度对比
🔥 问题6:两大锁机制对比
核心差异矩阵
| 维度 | synchronized | ReentrantLock |
|---|---|---|
| 实现级别 | JVM关键字 | JDK类实现 |
| 锁公平性 | 非公平 | 可选公平/非公平 |
| 条件队列 | 单队列 | 多Condition |
| 中断响应 | 不支持 | lockInterruptibly() |
| 锁绑定 | 自动释放 | 必须手动unlock() |
| 性能 | 优化后接近 | 高竞争更优 |
生产级ReentrantLock示例
public class BoundedBuffer {
private final ReentrantLock lock = new ReentrantLock(true); // 公平锁
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private final Object[] items = new Object[100];
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[count++] = x;
notEmpty.signal();
} finally {
lock.unlock();
}
}
}
三、Spring Bean生命周期与装配机制
🌟 Bean生命周期关键方法
生命周期流程图
关键方法重载示例
public class LifecycleBean implements
BeanNameAware, InitializingBean, DisposableBean {
@Override
public void setBeanName(String name) {
System.out.println("3. BeanName回调: " + name);
}
@PostConstruct
public void postConstruct() {
System.out.println("5. @PostConstruct");
}
@Override
public void afterPropertiesSet() {
System.out.println("6. InitializingBean");
}
public void customInit() {
System.out.println("7. 自定义init");
}
@PreDestroy
public void preDestroy() {
System.out.println("8. @PreDestroy");
}
@Override
public void destroy() {
System.out.println("9. DisposableBean");
}
public void customDestroy() {
System.out.println("10. 自定义destroy");
}
}
🌟 Spring集合注入与自动装配
集合注入示例
<bean id="complexObject" class="com.example.ComplexObject">
<property name="list">
<list>
<value>Java</value>
<ref bean="springBean"/>
</list>
</property>
<property name="map">
<map>
<entry key="key1" value="value1"/>
<entry key="key2" value-ref="springBean"/>
</map>
</property>
</bean>
运行 HTML
自动装配模式对比
| 模式 | 说明 | 注解示例 |
|---|---|---|
| byType | 按类型匹配 | @Autowired |
| byName | 按名称匹配 | @Resource |
| constructor | 构造器参数匹配 | 构造器参数上的@Autowired |
| no | 默认不自动装配 | - |
四、高频面试题强化训练
1. 如何选择synchronized和ReentrantLock?
-
选择synchronized:简单同步场景、追求代码简洁性
-
选择ReentrantLock:需要公平锁、可中断锁、超时锁、条件队列等高级特性
2. Bean生命周期回调执行顺序?
-
构造函数
-
@Autowired注入
-
@PostConstruct
-
InitializingBean.afterPropertiesSet()
-
自定义init-method
-
@PreDestroy
-
DisposableBean.destroy()
-
自定义destroy-method
3. 自动装配的歧义性如何解决?
@Autowired
@Qualifier("mainDataSource")
private DataSource dataSource;
// 或使用JSR-250
@Resource(name="mainDataSource")
private DataSource dataSource;
实战建议:
-
使用
jstack工具分析锁竞争情况 -
通过
@Order控制Bean初始化顺序 -
使用
@Lazy延迟初始化解决复杂依赖
💬 你在项目中遇到过哪些锁性能问题?如何优化的?
🎁 关注+转发,抽送《Java并发编程实战》电子书
