Skip to content

锁的优化

约 539 字大约 2 分钟

2025-09-20

[[线程安全#synchronized|synchronized]]的锁实现

public class SynchronizedDemo2 {
    Object object = new Object();
    public void method1() {
        synchronized (object) {
        }
        method2();
    }

    private static void method2() {
    }
}

字节码文件为 image 通过monitorentermonitorexit执行能够对象的锁计数器加一或减一,每一个对象在同一时间只能与一个monitor相关联,而一个monitor在同一时间只能被一个线程获得 image

JVM 的monitorentermonitorexit字节码依赖于底层操作系统的Mutex Lock实现,但Mutex Lock需要将当前线程挂起并进入内核态执行,切换的代价很昂贵,而大多数情况下可能只有单线程在进行,并不存在锁竞争,因此可以对锁的实现进行优化

锁的类型

JDK1.6+ 的 Synchronized 同步锁有四种状态

  • 无锁
  • 偏向锁
  • 轻量级锁
  • 重量级锁 随着锁竞争越来越激烈,由上到下逐渐升级,锁可以升级但不可以降级 32bit 下对象头的 mark wordimage

偏向锁

对于只有单线程不存在锁竞争的环境下,一个锁总是由一个线程获取,频繁的获取锁与释放锁会带来不必要的性能开销 若线程检查到对象是偏向锁,就会检查是否由当前线程持有,若是将直接执行同步代码,若不是则会尝试 CAS 获取竞争锁,若竞争失败将在下一个全局安全点升级为轻量级锁

轻量级锁

轻量级锁即自旋锁,没有抢到锁的线程将自旋,不断尝试获取锁,这对于能够很短时间内释放的锁能够避免用户态到内核态的开销 对于多次内旋无法获取到锁,为了避免自旋照成的 CPU 开销,会将锁升级为重量级锁

重量级锁

若线程无法获取到锁,且锁为重量级锁,线程将会进入等待队列,等待被唤醒

参考

synchronized详解