App*_*rew 10 java concurrency locking synchronized
当你synchronized在一个对象上有几个块时(比如说)obj那么Java如何检查所有这些块obj是相同还是不同?
例如:
public static f() {
synchronized ("xyz") {
...
}
}
Run Code Online (Sandbox Code Playgroud)
如果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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果你运行上面的代码,你将得到以下输出: -
f1: A
f1: A DONE
f1: B
f1: B DONE
Run Code Online (Sandbox Code Playgroud)
但是,如果我评论f1("A", "Str");和f1("B", "Str");行并取消注释它们上面的行,那么结果是: -
f1: A
f1: B
f1: A DONE
f1: B DONE
Run Code Online (Sandbox Code Playgroud)
由于Str版本工作,所以我期待Java可能使用equalscheck for synchronizedblock或者可能hashCode但是从第二次测试看起来似乎并非如此.
是String特例吗?
Thi*_*ilo 21
不,Java不equals用于锁定监视器.
锁定在对象实例本身上.所以,在某种程度上,它使用"==",如果你愿意(但实际上,这不是它的实现方式.每个对象都有一个特殊的插槽供当前的锁拥有者使用).
String没有特殊情况.
什么是用绳子发生的事情,不过,是字符串字面得到汇集,如果你曾经不止一次相同的文字多了,就会导致同一个实例(而new X产生不同的情况下,正如new String).如果你打电话intern给你的"新"字符串,你可能会看到相同的效果.