如果对象(比如说)synchronized
上有几个obj
块,那么Java如何检查所有这些obj
是否相同或不同?
例如:
public static f() {
synchronized ("xyz") {
...
}
}
如果两个线程同时调用上述函数f
,它们会阻塞另一个吗?请注意,每个线程都将获得String
对象的新实例。
为了检查这个,我编写了以下测试代码,看起来确实上面的块可以工作,但是还有其他意想不到的结果。
public class Test {
public static void main(String[] args){
new Thread() {
public void run() {
//f1("A", new X());
f1("A", "Str");
}
}.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//f1("B", new X());
f1("B", "Str");
}
public static void f1(String a, Object x) {
synchronized(x) {
System.out.println("f1: " + a);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("f1: " + a + " DONE");
}
}
private static class X {
public boolean equals(Object o) {
System.out.println("equals called");
return true;
}
public int hashCode() {
System.out.println("hashCode called");
return 0;
}
}
}
如果运行上面的代码,您将得到以下输出: -
f1: A
f1: A DONE
f1: B
f1: B DONE
但是,如果我对f1("A", "Str");
和f1("B", "Str");
行进行评论并取消注释其上方的行,则结果为: -
f1: A
f1: B
f1: A DONE
f1: B DONE
由于Str
版本有效,所以我希望Java使用equals
检查synchronized
块或hashCode
但是从第二次测试看来,它不是这个案子。
String
是特例吗?
答案 0 :(得分:21)
不,Java不会将equals
用于锁定监视器。
锁定在对象实例本身上。所以,在某种程度上,它使用“==”,如果你愿意(但实际上,这不是它的实现方式。每个对象都有一个特殊的插槽供当前的锁拥有者使用。)
String没有特殊情况。
Strings正在发生的事情是,字符串文字被合并,如果你有多次相同的文字,它将产生相同的实例(而new X
创建不同的实例,就像{{ {1}})。如果你在“新”字符串上调用new String
,你可能会看到相同的效果。