欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > 高薪程序员必修课-Java中 Synchronized锁的升级过程

高薪程序员必修课-Java中 Synchronized锁的升级过程

2025/4/19 8:48:36 来源:https://blog.csdn.net/qq_31095905/article/details/140160459  浏览:    关键词:高薪程序员必修课-Java中 Synchronized锁的升级过程

目录

前言

锁的升级过程

1. 偏向锁(Biased Locking)

原理:

示例:

2. 轻量级锁(Lightweight Locking)

原理:

示例:

3. 重量级锁(Heavyweight Locking)

原理:

示例:

注意事项

总结


前言

        在Java中,synchronized 关键字用于实现线程同步,确保在同一时间只有一个线程可以访问被保护的代码块。为了提高性能,Java对锁的实现进行了优化,采用了锁的升级机制。锁的升级过程包括从偏向锁、轻量级锁到重量级锁的升级。下面详细讲解锁的升级过程,并提供相应的示例。

锁的升级过程

  1. 偏向锁(Biased Locking)
  2. 轻量级锁(Lightweight Locking)
  3. 重量级锁(Heavyweight Locking)

1. 偏向锁(Biased Locking)

原理:

        偏向锁是为了优化只有一个线程访问同步块的情况。默认情况下,对象头中的标记字段(Mark Word)存储了偏向锁的线程ID。只有当另一个线程尝试获取锁时,偏向锁才会升级为轻量级锁。

示例:
public class BiasedLockingExample {private static final Object lock = new Object();public static void main(String[] args) {synchronized (lock) {// 第一个线程获得偏向锁System.out.println("Thread 1 has acquired the biased lock.");}}
}

在这个示例中,synchronized 关键字使得 lock 对象在第一次被线程获取时进入偏向锁状态。

2. 轻量级锁(Lightweight Locking)

原理:

        当另一个线程尝试获取已偏向的锁时,偏向锁升级为轻量级锁。轻量级锁使用CAS(Compare-And-Swap)操作来避免阻塞。当竞争不激烈时,轻量级锁的性能优于重量级锁。

示例:
public class LightweightLockingExample {private static final Object lock = new Object();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {synchronized (lock) {// 第一个线程获得偏向锁System.out.println("Thread 1 has acquired the lock.");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});Thread t2 = new Thread(() -> {synchronized (lock) {// 第二个线程尝试获取锁,偏向锁升级为轻量级锁System.out.println("Thread 2 has acquired the lock.");}});t1.start();Thread.sleep(100); // 确保t1先获得锁t2.start();t1.join();t2.join();}
}

在这个示例中,第二个线程尝试获取已经被第一个线程偏向的锁,导致偏向锁升级为轻量级锁。

3. 重量级锁(Heavyweight Locking)

原理:

        当多个线程频繁竞争同一个锁时,轻量级锁会不断地进行CAS操作,这时轻量级锁会升级为重量级锁(互斥锁)。重量级锁会使用操作系统的同步机制,使得其他线程在获取锁时进入阻塞状态,减少CPU的自旋消耗。

示例:
public class HeavyweightLockingExample {private static final Object lock = new Object();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {synchronized (lock) {// 第一个线程获得锁System.out.println("Thread 1 has acquired the lock.");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}});Thread t2 = new Thread(() -> {synchronized (lock) {// 第二个线程尝试获取锁,锁升级为重量级锁System.out.println("Thread 2 has acquired the lock.");}});Thread t3 = new Thread(() -> {synchronized (lock) {// 第三个线程尝试获取锁,锁已是重量级锁System.out.println("Thread 3 has acquired the lock.");}});t1.start();Thread.sleep(100); // 确保t1先获得锁t2.start();Thread.sleep(100); // 确保t2在t1之后尝试获取锁t3.start();t1.join();t2.join();t3.join();}
}

在这个示例中,第三个线程尝试获取已经被第二个线程竞争的轻量级锁,导致轻量级锁升级为重量级锁。

注意事项

  1. 适用场景

    • 偏向锁适用于只有一个线程访问同步块的场景。
    • 轻量级锁适用于多个线程交替访问同步块且竞争不激烈的场景。
    • 重量级锁适用于多个线程频繁竞争同一个锁的场景。
  2. 锁升级不可逆

    • 一旦锁从偏向锁升级为轻量级锁或重量级锁,无法降级为偏向锁。为了性能优化,尽量避免频繁的锁竞争。
  3. 启用和禁用偏向锁

    • 默认情况下,偏向锁是启用的。如果需要禁用,可以在JVM启动参数中添加 -XX:-UseBiasedLocking

总结

        Java中 synchronized 锁的升级过程包括从偏向锁、轻量级锁到重量级锁:

  1. 偏向锁:优化单线程访问的场景,减少不必要的同步开销。
  2. 轻量级锁:通过CAS操作进行自旋,适用于竞争不激烈的场景。
  3. 重量级锁:使用操作系统同步机制进行阻塞,适用于高竞争的场景。

通过了解锁的升级过程,可以更好地优化并发程序的性能,避免不必要的锁竞争和性能开销。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词