synchronized 的锁升级策略
时间: 2023-05-30 21:05:34 浏览: 125
Java 中的 synchronized 关键字是一种内置锁(也称为监视器锁),用于保护共享资源的并发访问。在 JVM 中,synchronized 锁的状态分为四种级别,即无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。当线程请求一个 synchronized 锁时,JVM 会根据当前锁的状态进行锁升级,以提高并发效率和减少系统开销。
锁升级策略如下:
1. 无锁状态:当没有线程请求锁时,锁处于无锁状态。
2. 偏向锁状态:当只有一个线程请求锁时,JVM 会将锁升级为偏向锁状态。此时,JVM 会给锁关联一个线程 ID,表示这个锁被这个线程占用。这样,当这个线程再次请求锁时,JVM 可以快速地判断该锁是否被该线程占用,从而避免了锁的竞争。
3. 轻量级锁状态:当有多个线程请求锁时,JVM 会将锁升级为轻量级锁状态。在这种状态下,JVM 会使用 CAS 操作来尝试获取锁,如果获取成功,则说明该锁没有竞争,可以直接占用。如果获取失败,则说明该锁有竞争,需要升级为重量级锁状态。
4. 重量级锁状态:当多个线程竞争一个锁时,JVM 会将锁升级为重量级锁状态。在这种状态下,JVM 会将锁的状态保存在操作系统内核中,并使用操作系统提供的互斥量来保证锁的安全性。
锁升级的过程是自动进行的,开发者不需要手动干预。这种锁升级策略可以有效地提高并发效率和减少系统开销,但在极端情况下,也可能造成性能问题。
相关问题
synchronized 轻量级锁比重量级锁先获取到锁吗
### Java `synchronized` 下轻量级锁与重量级锁的获取顺序
在Java中,`synchronized`关键字用于实现同步控制,确保同一时刻只有一个线程能够执行特定代码段。对于锁的获取过程,存在不同级别的锁机制,即轻量级锁和重量级锁。
#### 锁的状态转换
对象头中的Mark Word记录着锁的信息,在初始状态下为无锁状态。当第一个线程尝试获取锁时,会先检查是否已加锁以及是否有其他线程持有此锁。如果没有,则通过CAS操作快速设置锁标志位并关联上当前线程ID,形成轻量级锁[^1]。
```java
public class SyncExample {
private final Object lock = new Object();
public void syncMethod() {
synchronized (lock) { // 尝试获得轻量级锁
System.out.println(Thread.currentThread().getName() + " acquired the lock");
}
}
}
```
一旦有第二个线程试图访问已被占用的对象锁,此时无法直接取得轻量级锁,便会触发锁膨胀至重量级锁的过程。具体来说:
- **轻量级锁阶段**:新来的线程会在自己的栈帧内创建Lock Record结构体,并利用CAS指令去替换目标对象头部指向自己记录副本的位置。成功则意味着获得了锁所有权;失败说明已有其它活动线程正在争夺相同资源。
- **重量级锁阶段**:若多次自旋仍未获准进入临界区(通常是因为长时间的竞争),那么将会进一步升级成重量级锁模式。这时操作系统介入调度管理这些等待中的线程,采用传统的阻塞/唤醒策略处理它们之间的互斥关系[^4]。
因此,在`synchronized`作用范围内,默认情况下首先是争取成为轻量级锁,只有遇到冲突才会逐步演变为更重形式的锁形态——重量级锁。
阅读全文