在 Java 中,synchronized
关键字可以用来实现同步,它可以接收不同的参数,主要有以下两种常见用法:以对象作为参数和以类作为参数。
一、synchronized
关键字的作用
synchronized
关键字用于确保在同一时刻只有一个线程可以访问被它修饰的代码块或方法。它通过对对象或类进行加锁来实现线程之间的同步,防止多个线程同时访问共享资源时出现数据不一致或其他并发问题。
二、以对象作为参数(对象锁)
- 代码示例:
class MyClass {private Object lockObject = new Object();public void method1() {synchronized (lockObject) {// 同步代码块,访问共享资源System.out.println("Thread " + Thread.currentThread().getName() + " is in synchronized block.");}}
}
- 作用和特点:
- 当一个线程进入
synchronized
代码块时,它会获取指定对象的锁。只有持有这个锁的线程可以执行这个代码块,其他线程如果也尝试进入这个代码块,就会被阻塞,直到锁被释放。 - 这种方式通常用于在一个类的特定方法中对某个特定的对象进行同步操作,确保多个线程在访问这个对象的相关代码时是线程安全的。
- 当一个线程进入
三、以类作为参数(类锁)
- 代码示例:
class MyClass {public static synchronized void method2() {// 同步静态方法,访问共享资源System.out.println("Thread " + Thread.currentThread().getName() + " is in static synchronized block.");}
}
或者
class MyClass {public void method3() {synchronized (MyClass.class) {// 同步代码块,访问共享资源System.out.println("Thread " + Thread.currentThread().getName() + " is in synchronized block on class.");}}
}
- 作用和特点:
- 当
synchronized
作用于静态方法或者使用类作为参数时,它获取的是类级别的锁,也称为类锁。这意味着不同的线程在访问这个类的任何静态同步方法或者使用类作为参数的同步代码块时,都会被同步。 - 类锁是针对整个类的,而不是针对类的特定实例。无论有多少个实例对象,只要一个线程在访问静态同步方法或者类锁保护的代码块,其他线程就不能同时访问。
- 当
四、两者区别
- 锁的范围:
- 对象锁是针对特定的对象实例的,不同的对象实例有不同的锁。
- 类锁是针对整个类的,所有的对象实例共享同一个类锁。
- 适用场景:
- 对象锁适用于多个线程需要同步访问同一个对象的特定资源的情况。
- 类锁适用于多个线程需要同步访问类的静态资源或者需要对整个类的行为进行同步控制的情况。
- 并发性能:
- 对象锁可以允许多个线程同时访问不同的对象实例,只要它们不竞争同一个对象的锁,因此在某些情况下可以提供更好的并发性能。
- 类锁在同一时刻只允许一个线程访问静态资源或者类级别的同步代码块,可能会对并发性能产生一定的影响,特别是当多个线程频繁访问静态资源时。