synchronized的底层原理面试题
时间: 2025-03-05 14:39:16 浏览: 56
### Java `synchronized` 关键字底层实现原理
#### 锁的状态及其转换机制
在Java虚拟机中,对象头包含了Mark Word用于存储对象的元数据信息。对于`synchronized`关键字而言,其主要通过锁状态的变化来控制线程间的访问[^1]。
- **无锁状态**:当没有任何线程持有该对象上的锁时处于此状态。
- **偏向锁**:如果只有一个线程尝试获取某个对象的锁,则会进入偏向模式,减少不必要的加锁开销。
- **轻量级锁**:一旦有第二个线程竞争同一个对象上的锁就会升级为轻量级锁;此时采用自旋的方式等待当前拥有锁的线程释放锁资源。
- **重量级锁**:若自旋次数达到一定阈值仍未获得锁,则进一步升级成重量级锁,使后续请求锁失败的线程挂起并放入阻塞队列中排队等候。
```java
public class MonitorTest {
static final Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + ": acquired monitor");
}
});
Thread t2 = new Thread(() => {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + ": acquired monitor");
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
```
上述代码展示了两个线程试图同时获取同一把锁的情况。根据锁的竞争情况,可能会经历从偏向锁到轻量级锁再到重量级锁的过程[^3]。
#### 对象监视器(Monitor)
每当使用`synchronized`修饰方法或代码块的时候,实际上是在创建一个关联的对象监视器实例。每个Java对象都有与其对应的monitor记录结构体,其中保存了关于锁定的信息,比如:
- Owner字段表示哪个线程正在占有这把锁;
- Entry Queue用来存放那些被阻塞而无法立即得到锁所有权的其他线程;
- Wait Set则收集因调用了wait()函数暂停执行但仍需继续争夺相同锁的所有权的线程列表。
#### 自旋锁优化
为了避免频繁上下文切换带来的性能损耗,在某些情况下JVM会对轻量级锁采取自旋策略——即让后面到来想要取得锁却暂时得不到它的线程先忙等一段时间再重新尝试而不是立刻加入睡眠状态。这种方式可以有效提高程序效率特别是短时间内的高频率互斥操作场景下表现尤为明显。
#### 性能考量与锁消除/粗化
编译期优化手段之一就是尽可能地移除显式的同步指令以降低运行时刻成本。例如局部变量即使声明为final也不必担心逃逸问题因而不需要额外保护措施即可安全共享给多个CPU核心处理;另外还有可能将一系列连续的小范围临界区合并扩大从而减少进出监控区域所带来的消耗。
阅读全文
相关推荐


















