我有以下仅包含一个字段的类i
。对该字段的访问由对象的锁(“this”)保护。当实现 equals() 时,我需要锁定这个实例 (a) 和另一个实例 (b)。如果线程 1 调用 a.equals(b),同时线程 2 调用 b.equals(a),则两个实现中的锁定顺序相反,可能会导致死锁。
我应该如何为具有同步字段的类实现 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;
}
}
尝试同步equals
and hashCode
对象内部将无法正常工作。考虑以下情况:HashMap
使用hashCode
发现对象将位于哪个“桶”中,然后使用equals
顺序搜索桶中的所有对象。
如果允许对象以改变结果的方式发生变异hashCode
or equals
你最终可能会遇到这样的情况HashMap
calls hashCode
。它获取锁,获取哈希并再次释放锁。HashMap
然后继续计算要使用哪个“桶”。但之前HashMap
可以获取锁 等于其他人获取锁并改变对象,以便equals
与之前的值不一致hashCode
。这将导致灾难性的结果。
The hashCode
和 equals 方法在很多地方都有使用,并且是 Java 集合 API 的核心。重新考虑不需要同步访问这些方法的应用程序结构可能很有价值。或者至少不同步对象本身。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)