当你在一个对象(比如说obj
)上拥有多个synchronized
代码块时,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
是否是一个特例?