在Java编程语言中,synchronized
关键字用于实现线程同步,确保多线程环境中对共享资源的安全访问。当一个方法被声明为synchronized
时,它保证同一时刻只有一个线程可以执行该方法。synchronized
可以修饰普通方法(实例方法)和静态方法,但它们之间存在一些重要的区别。
1. 锁的作用范围不同
普通方法(实例方法)
- 当一个
synchronized
普通方法被调用时,这个锁作用于当前对象的实例。 - 如果一个线程正在执行某个对象的
synchronized
普通方法,则其他线程不能同时执行同一个对象上的任何synchronized
普通方法,但可以执行该对象的非synchronized
方法或其他对象上的任何方法。 - 实例方法的锁通常被称为“对象锁”。
静态方法
- 当一个
synchronized
静态方法被调用时,这个锁作用于整个类的所有实例。 - 因为静态方法是类级别的,所以如果一个线程正在执行某个类的
synchronized
静态方法,则其他线程不能同时执行该类的任何其他synchronized
静态方法。 - 静态方法的锁通常被称为“类锁”,也被称为“ClassLock”。
2. 锁的获取方式不同
普通方法(实例方法)
- 对象的实例方法需要获取该对象的锁才能执行。
- 调用
synchronized
普通方法的线程会自动获取并持有对象锁,直到方法执行完毕或抛出异常。
静态方法
- 静态方法需要获取该类的锁才能执行。
- 调用
synchronized
静态方法的线程会自动获取并持有类锁,直到方法执行完毕或抛出异常。
3. 锁的持有者不同
普通方法(实例方法)
- 每个对象实例都有自己的锁。
- 同一个类的不同实例之间互不影响,即一个线程可以同时执行多个对象上的
synchronized
普通方法。
静态方法
- 类级别的锁意味着所有实例共享一个锁。
- 一个线程获取了类锁后,其他线程无法再获取该锁,直到第一个线程释放锁。
4. 示例代码
普通方法示例
public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
静态方法示例
public class Counter {
public static synchronized void printMessage(String message) {
System.out.println(message);
}
}
总结
synchronized
修饰普通方法和静态方法的主要区别在于锁的范围和持有者。普通方法使用的是对象锁,而静态方法使用的是类锁。理解这些区别有助于开发人员更好地管理多线程环境下的资源访问,从而避免并发问题,如死锁和数据不一致等。正确使用synchronized
关键字可以有效地提高程序的稳定性和性能。