【发布时间】:2016-01-27 18:50:27
【问题描述】:
我已阅读有关线程安全延迟初始化的内容,并查看了 String 类中 hashCode 方法的实现。显然这种方法是线程安全的,我为另一个类(不可变)制作了自己的版本。
private int hashcode;
@Override
public int hashCode() {
int h = hashcode;
if (h == 0 && array.length > 0) {
hashcode = (h = Arrays.hashCode(array));
}
return h;
}
我的问题是:它真的是线程安全的吗?我不明白为什么。 我看不出是什么阻止了一个线程进入该方法,而另一个线程仍在其中,但也许它弄错了。
【问题讨论】:
-
线程安全不等同于互斥。这并不意味着一次只有一个线程可以执行该方法。这意味着,无论有多少线程调用该方法,无论以何种顺序,同时或不并发,它们都会得到正确的结果,并使对象处于正确的状态。该方法的线程安全主要取决于数组的不变性。
-
好的,谢谢。我想我现在明白了,可能发生的更糟糕的是哈希码被计算了几次。但这并不危险,因为对象是不可变的,哈希码总是相同的。
-
实际上并没有更糟。更糟糕的是 Arrays.hashCode() 返回 0,这将导致 hashCode()每次都被重新计算。此问题已被用作一种通过提交已知具有 0 hashCode 的长字符串来创建巧妙 DDOS 攻击的方法。
-
我应该添加一个条件来防止这种情况发生吗?
-
布尔值不允许在没有某种同步的情况下自动设置 hashCode:一个线程会切换布尔值并设置 hashCode,另一个线程可以看到切换后的布尔值,但看不到正确的 hashCode .
标签: java thread-safety lazy-initialization