返回

深入浅出,剖析Synchronized实现的奥秘

后端

Java 中的 synchronized 是多线程编程中不可或缺的同步工具,它可以保证临界区的代码在同一时刻只有一个线程执行,从而避免数据竞争和线程安全问题。那么,synchronized 究竟是如何在底层实现的呢?本文将深入剖析 synchronized 的底层实现机制,揭开它的神秘面纱。

synchronized 的底层实现

synchronized 关键字在底层是通过一个名为 monitor 的对象实现的。每个对象都有一个与其关联的 monitor 对象,monitor 对象包含一个称为锁标识(lock identity)的字段和一个等待队列(wait queue)。当一个线程尝试进入一个同步块时,它会首先尝试获取该同步块关联的 monitor 对象的锁。如果锁已被其他线程持有,则尝试获取锁的线程将被阻塞并添加到等待队列中。

一旦线程获取了锁,它就可以独占地执行同步块中的代码。当线程执行完同步块后,它会释放锁,以便其他线程可以获取该锁并执行同步块中的代码。

偏向锁优化

为了提高 synchronized 的性能,Java 引入了偏向锁优化。偏向锁优化是指当一个线程第一次获取一个对象的锁时,JVM 会将该对象的锁标识指向该线程。这意味着,当该线程再次尝试获取该对象的锁时,JVM 可以直接将锁授予该线程,而无需进行任何竞争。

偏向锁优化可以显著提高无竞争情况下的 synchronized 性能。然而,如果多个线程竞争同一把锁,则偏向锁优化会被撤销,JVM 将恢复到传统的锁竞争机制。

代码示例

下面是一个简单的 Java 代码示例,展示了 synchronized 的底层实现:

public class SynchronizedExample {

    private int counter;

    public synchronized void increment() {
        counter++;
    }

}

当一个线程调用 increment() 方法时,它会尝试获取 SynchronizedExample 对象关联的 monitor 对象的锁。如果锁已被其他线程持有,则尝试获取锁的线程将被阻塞并添加到等待队列中。

一旦线程获取了锁,它就可以独占地执行 increment() 方法中的代码。当线程执行完 increment() 方法后,它会释放锁,以便其他线程可以获取该锁并执行 increment() 方法中的代码。

总结

synchronized 关键字通过 monitor 对象和偏向锁优化在底层实现了线程同步。monitor 对象包含一个锁标识和一个等待队列,用于管理锁的竞争。偏向锁优化可以提高无竞争情况下的 synchronized 性能。通过理解 synchronized 的底层实现,我们可以更好地利用它来编写安全且高效的多线程程序。