在Java中,synchronized关键字用于实现线程同步,以保护共享资源的访问。在多线程环境中,Java的锁机制会根据不同的线程竞争情况,动态地对锁的状态进行升级,以提高程序的执行效率。锁的升级过程大致可以分为几种状态:无锁状态、偏向锁、轻量级锁和重量级锁。

1. 无锁状态

初始状态为无锁状态,在没有线程请求锁的情况下,锁处于无锁状态,任何线程都可以访问相应的资源。这种状态下无需任何同步机制,执行效率较高。

2. 偏向锁

当一个线程第一次请求锁时,JVM会将锁的状态设置为偏向锁,并把锁对象的偏向线程ID设置为这个线程ID。这意味着,如果后续的线程再次请求这个锁,并且是同一个线程,就不会进行任何额外的竞争,直接获取锁。这种机制大大减少了同步中的开销。

public class BiasedLockExample {
    public synchronized void biasedLockMethod() {
        System.out.println(Thread.currentThread().getName() + "获取了偏向锁");
        // 执行一些操作
    }

    public static void main(String[] args) {
        BiasedLockExample example = new BiasedLockExample();
        Thread t1 = new Thread(example::biasedLockMethod);
        t1.start();
    }
}

3. 轻量级锁

当有多个线程争抢偏向锁,且偏向锁被其他线程请求时,JVM会将锁的状态升级为轻量级锁。此时,轻量级锁会使用一个标志位进行管理,如果当前线程获取锁成功,其他线程需要通过自旋的方式来尝试获取锁。这种方式的开销比重量级锁要小。

public class LightweightLockExample {
    private final Object lock = new Object();

    public void lightweightLockMethod() {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + "获取到了轻量级锁");
            // 执行一些操作
        }
    }

    public static void main(String[] args) {
        LightweightLockExample example = new LightweightLockExample();
        Thread t1 = new Thread(example::lightweightLockMethod);
        Thread t2 = new Thread(example::lightweightLockMethod);
        t1.start();
        t2.start();
    }
}

4. 重量级锁

当轻量级锁被其他线程长时间占用,这时可能会导致自旋的开销变得很大。为了避免锁竞争造成的性能损耗,JVM会将轻量级锁升级为重量级锁。此时所有的请求锁的线程将被挂起,只有释放锁的线程才能唤醒被挂起的线程。

public class HeavyweightLockExample {
    private final Object lock = new Object();

    public void heavyweightLockMethod() {
        synchronized (lock) {
            System.out.println(Thread.currentThread().getName() + "获取到了重量级锁");
            // 执行一些操作
            try {
                Thread.sleep(2000); // 模拟长期占用锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        HeavyweightLockExample example = new HeavyweightLockExample();
        Thread t1 = new Thread(example::heavyweightLockMethod);
        Thread t2 = new Thread(example::heavyweightLockMethod);
        t1.start();
        t2.start();
    }
}

小结

上面的示例通过不同的锁状态演示了Java中的synchronized关键字是如何管理多个线程之间的竞争关系的。从无锁到偏向锁、轻量级锁再到重量级锁,这一系列过程旨在动态优化锁的性能,以适应实际的线程竞争情况。理解锁的升级过程是优化多线程程序性能的重要一环,能帮助开发人员在设计系统时更好地使用锁机制。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部