在 Java 中,每个对象都有一个关联的监视器(monitor),也称为锁。当你使用 `synchronized` 关键字对某个对象进行同步时,实际上是获取了这个对象的监视器。对于基本数据类型的包装类对象(比如 `Integer`、`Long`、`Double` 等),由于它们是不可变的,因此每次对它们的修改都会创建一个新的对象,而不是在原对象上进行修改。
考虑以下代码:
public class Example {
private static Integer counter = 0;
public static synchronized void increment() {
counter++;
}
}
在这个例子中,`counter` 是 `Integer` 类型。尽管 `increment` 方法使用了 `synchronized` 关键字,但这并不能保证线程安全,因为每次 `counter++` 会创建一个新的 `Integer` 对象。不同线程可能获得不同的对象锁,无法实现真正的互斥。解决这个问题的一种方法是使用 `synchronized` 关键字锁住一个特定的对象,而不是基本数据类型的包装类对象:
public class Example {
private static final Object lock = new Object();
private static Integer counter = 0;
public static void increment() {
synchronized (lock) {
counter++;
}
}
}
在这个例子中,我们使用了一个额外的 `Object` 类型的对象 `lock`,并在 `increment` 方法中使用 `synchronized (lock)`,这样确保了不同线程都锁住了相同的对象,从而实现了互斥。这种方式可以避免基本数据类型的包装类对象由于不可变性而无法起到锁的作用的问题。