Когда у вас есть пара блоков 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
особым случаем?