Tengo la siguiente clase que contiene un solo campo i
. El acceso a este campo está protegido por el bloqueo del objeto ("esto"). Al implementar equals() necesito bloquear esta instancia (a) y la otra (b). Si el hilo 1 llama a.equals (b) y al mismo tiempo el hilo 2 llama a b.equals (a), el orden de bloqueo es inverso en las dos implementaciones y puede dar como resultado un interbloqueo.Sincronización correcta equals() en Java
¿Cómo debo implementar equals() para una clase que tiene campos sincronizados?
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;
}
}
Tiene razón en que un valor podría cambiar inmediatamente después de la comparación, pero como cuando el valor envuelto es más interesante que un 'int' primitivo, existe la posibilidad de que ese valor esté en un estado incoherente a menos que se sincronice mientras se examinan sus partes. –
Es cierto, pero todavía tiene el problema de qué hacer después de que el igual – Mark
en realidad, el problema es de visibilidad. sin usar sincronizado, un pedido válido aún podría dar como resultado un resultado inesperado (es decir, un valor establecido anteriormente no es visible cuando debería). – jtahlborn