我将通过以下3种情况来解释这个问题。
情况一:
我正在使用共享锁进行同步,如下所示:
private static final String SHARED_LOCK = "shared_lock";
private static int i = 0;
private static int j = 0;
void increment() {
synchronized (SHARED_LOCK) {
i++;
j++;
}
}
而且工作正常。
案例二:
现在,我在这里所做的更改不是使用共享锁,而是考虑通过执行以下操作来使用本地锁:
private static int i = 0;
private static int j = 0;
void increment() {
final String LOCAL_LOCK = "local_lock";
synchronized (LOCAL_LOCK) {
i++;
j++;
}
}
而且我发现代码仍然可以正常工作,而同步仍然可以工作。
情况三:
但是,当我将本地位置更改为:
final String LOCAL_LOCK = new String("local_lock");
然后同步消失了。如此看来,在CASE II中,本地锁能够提供同步,因为Java自动为我们自动完成了String字面量的插入,但在CASE III中,因为每次每次都显式创建一个新的String时,同步就不会发生。
回到我最初的问题。有人认为CASE II不是实现同步的正确方法吗?如果可以,还请您说明原因?
提前致谢,
SacTiw。
最佳答案
这里非常重要的一点是,使用“可以规范化”的对象(例如可以被嵌入的String
或可以共享的Integer
常量)基本上可以让您使用相同的锁定对象作为另一类。
就像您想象的那样,这是一个非常糟糕的主意。通过使用与另一个类相同的锁,可以在以后尝试确定应用程序死锁的原因时,基本上可以为自己提供一个痛苦的调试世界。
如果您需要类中的私有锁,请仅通过new
运算符获取它,以确保它是一个完全唯一的对象。
(我相信其中一个Java Puzzlers演示文稿可能已经涵盖了这一点;其他一些示例引用是here和here)
关于java - 使用本地锁代替共享锁进行同步是否安全?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3456871/