Mam następującą klasę, która zawiera tylko jedno pole i
. Dostęp do tego pola jest chroniony przez blokadę obiektu ("to"). Podczas implementacji equals() muszę zablokować tę instancję (a) i drugą (b). Jeśli wątek 1 wywoła a.equals (b) i jednocześnie wątek 2 wywoła b.equals (a), kolejność blokowania będzie odwrotna w obu implementacjach i może spowodować zakleszczenie.Prawidłowa synchronizacja równań() w języku Java
Jak należy zaimplementować equals() dla klasy, która ma zsynchronizowane pola?
public class Sync {
// @GuardedBy("this")
private int i = 0;
public synchronized int getI() {return i;}
public synchronized void setI(int i) {this.i = i;}
public int hashCode() {
final int prime = 31;
int result = 1;
synchronized (this) {
result = prime * result + i;
}
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Sync other = (Sync) obj;
synchronized (this) {
synchronized (other) {
// May deadlock if "other" calls
// equals() on "this" at the same
// time
if (i != other.i)
return false;
}
}
return true;
}
}
Masz rację, że jedna wartość może się zmienić natychmiast po stosunku, ale tak jak wtedy, gdy zawijana wartość jest bardziej interesująca niż prymitywna "int", istnieje możliwość, że ta wartość będzie w niespójnym stanie, chyba że zostanie zsynchronizowana, podczas gdy jej części są badane. –
Prawda, ale nadal masz problem z tym, co zrobić po równym – Mark
w rzeczywistości, kwestia jest widoczność. bez użycia synchronizacji, poprawna kolejność może nadal skutkować nieoczekiwanym wynikiem (tj. wcześniej ustawiona wartość nie jest widoczna, kiedy powinna być). – jtahlborn