当你在一个对象上有几个synchronized
block 时(比如说)obj
那么Java如何检查所有这些obj
是否是相同还是不同?
例如:
public static f() {
synchronized ("xyz") {
...
}
}
如果上面的函数 f
被两个线程同时调用,它们会阻塞另一个吗?请注意,每个线程都会获得一个新的 String
对象实例。
为了检查这一点,我编写了以下测试代码,看起来上面的 block 确实可以工作,但是还有其他意想不到的结果。
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
block 或者 hashCode
但从第二次测试看来,情况完全不是这样。
String
是特例吗?
最佳答案
不,Java 不使用 equals
作为锁监视器。
锁在对象实例本身上。所以,在某种程度上,它使用了“==”,如果你愿意的话(但实际上,这不是它的实现方式。每个对象都有一个用于当前锁所有者的特殊插槽)。
String 没有特殊情况。
但是,字符串发生的事情是,字符串字面量被合并,如果您多次使用相同的字面量,它将产生相同的实例(而 new X
创建不同的实例, new String
)。如果您对"new"字符串调用 intern
,您可能会看到相同的效果。
关于Java 锁 : How equality check for Monitor locks is done in synchronized block?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12139849/