面试题:Synchronized 修饰静态方法和修饰普通方法有什么区别?

在 Java 中,synchronized 关键字可以用来修饰实例方法、静态方法或者代码块。当它用于修饰静态方法和普通(实例)方法时,存在一些重要的区别,主要体现在锁的对象以及锁定的范围上。

锁定对象的区别

  1. 修饰实例方法
    • 当 synchronized 用于修饰一个实例方法时,它锁定的是调用该方法的对象实例(即当前对象实例 this)。这意味着每一个对象实例都有其自己的锁,不同实例之间的锁是相互独立的。
    • 示例:
      public class InstanceSyncExample {
          public synchronized void instanceMethod() {
              // 此处的同步块锁定的是当前对象实例 this
          }
      }
    • 在上面的例子中,如果多个线程试图访问同一个 InstanceSyncExample 实例的 instanceMethod() 方法,它们将被串行化执行,因为它们都在竞争同一个实例级别的锁。
      但是,如果这些线程操作的是不同的 InstanceSyncExample 实例,则每个实例都有自己独立的锁,因此可以并行执行各自的方法。
  2. 修饰静态方法
    • 当 synchronized 用于修饰静态方法时,它锁定的是该类对应的Class 对象。这是因为静态成员属于类级别而非实例级别,所以静态同步方法使用的锁是整个类的一个单一锁,无论创建了多少个该类的实例,所有实例共享这个锁。
    • 示例:
      public class StaticSyncExample {
          public static synchronized void staticMethod() {
              // 此处的同步块锁定的是 StaticSyncExample 类的 Class 对象
          }
      }
    • 在这个例子中,不论有多少个 StaticSyncExample 的实例存在,所有的线程在调用 staticMethod() 方法时都会竞争同一个锁,即 StaticSyncExample.class 这个锁对象。这意味着即使是从不同的实例调用此静态同步方法,也只能有一个线程能够执行该方法。

总结

  • 锁定对象synchronized 修饰实例方法时锁定的是当前对象实例;而修饰静态方法时锁定的是类的 Class 对象。
  • 作用范围:对于实例方法,锁定的作用范围限于特定的对象实例;而对于静态方法,锁定的作用范围覆盖了整个类的所有实例。
  • 应用场景:如果你需要确保对某个类的所有实例中的某个资源进行同步访问,那么应该使用静态同步方法。反之,如果你只需要保证在同一对象实例内的同步访问,那么使用实例同步方法即可。

了解这两者的区别对于编写高效且正确的并发程序至关重要,尤其是在处理多线程环境下的资源共享问题时。

THE END
喜欢就支持一下吧
点赞15 分享