我会尝试通过以下三种情况来解释这个问题。 案例一: 我是用使用这样的同步共享锁:使用本地锁而不是共享锁进行同步安全吗?
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++;
}
}
而且我发现代码仍然是工作罚款是同步仍在工作。
案例三: 然而,当我改变了当地LOCL这样:
final String LOCAL_LOCK = new String("local_lock");
然后同步走了。所以看起来在CASE II中,本地锁能够提供同步,因为Java会为我们自动执行String实例,但是在CASE III中,我每次都明确地创建一个新的String,因此没有发生同步。
所以回到我原来的问题。有没有人认为CASE II不是实现同步的正确方法?如果是的话,请你也提一下为什么?
在此先感谢, SacTiw。
所以在这里你的意思是情况2可能会导致一些其他线程访问其他类可能会开始使用相同的锁作为这个类,这将导致性能差和痛苦的调试。对? – sactiw 2010-08-12 09:57:12
在Java语言规范中提到,在Java中,不同包中不同类中的文字字符串(不可变)同样代表对同一个字符串对象的引用。这个规则适用于所有原始对象,因为它们都是不可变的。 因此,这意味着如果我们按情况2行事,可能导致性能下降,并在面临死锁时进行痛苦的调试。 所以我认为我可以说,我的问题可以通过案例2进行同步,但它并不是所有推荐的使用方式。 – sactiw 2010-08-12 14:24:19
绝对,sactiw。使用除私有的,不可访问的其他类对象以外的任何东西通常是一个非常糟糕的主意。如果你通过'new'得到一个对象,你就知道它是你自己的(只要你不泄漏它)。 – Cowan 2010-08-12 21:04:35