У меня есть следующий класс, который содержит только одно поле i
. Доступ к этому полю защищен блокировкой объекта («это»). При реализации equals() мне нужно заблокировать этот экземпляр (a) и другой (b). Если поток 1 вызывает a.equals (b), и в то же время поток 2 вызывает b.equals (a), порядок блокировки является обратным в двух реализациях и может привести к тупиковой ситуации.Правильно синхронизировать equals() в Java
Как реализовать equals() для класса, который имеет синхронизированные поля?
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;
}
}
Вы правы, что одна величина может измениться сразу после сравнения, но так как когда обернутое значение более интересно, чем примитивное 'int', существует вероятность того, что это значение находится в противоречивом состоянии, если не синхронизировано, пока его части проверяются. –
Правда, но у вас все еще есть проблема, что делать после равных – Mark
на самом деле, проблема одна из видимости. без использования синхронизации, действительное упорядочение может по-прежнему приводить к неожиданному результату (т. е. ранее установленное значение не отображается, когда оно должно быть). – jtahlborn