java 字符串哈希码缓存机制
java String hashcode caching mechanism
查看 Java 的 String
class 我们可以看到哈希码在第一次评估后被缓存。
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
其中hash
是一个实例变量。我有一个问题,为什么我们需要那个 h
额外变量?
仅仅是因为 hash
值在循环中发生变化,没有中间临时变量的解决方案不是线程安全的。考虑在多个线程中调用此方法。
说 thread-1
开始了 hash
计算,它不再是 0
。片刻之后 thread-2
在同一对象上调用相同的方法 hashCode()
并发现 hash
不是 0
,但 thread-1
尚未完成其计算。结果,在 thread-2
中将使用错误的 hash
(未完全计算)值。
这是一种简单且廉价的同步机制。
如果一个线程第一次调用 hashCode(),而第二个线程在第一个线程计算哈希值时再次调用它,则第二个线程将 return 一个不正确的哈希值(在第一个线程中计算)如果直接使用属性。
说的很简单:local primitive h
很好 local;因此线程安全;与共享的 hash
相反。
查看 Java 的 String
class 我们可以看到哈希码在第一次评估后被缓存。
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
其中hash
是一个实例变量。我有一个问题,为什么我们需要那个 h
额外变量?
仅仅是因为 hash
值在循环中发生变化,没有中间临时变量的解决方案不是线程安全的。考虑在多个线程中调用此方法。
说 thread-1
开始了 hash
计算,它不再是 0
。片刻之后 thread-2
在同一对象上调用相同的方法 hashCode()
并发现 hash
不是 0
,但 thread-1
尚未完成其计算。结果,在 thread-2
中将使用错误的 hash
(未完全计算)值。
这是一种简单且廉价的同步机制。
如果一个线程第一次调用 hashCode(),而第二个线程在第一个线程计算哈希值时再次调用它,则第二个线程将 return 一个不正确的哈希值(在第一个线程中计算)如果直接使用属性。
说的很简单:local primitive h
很好 local;因此线程安全;与共享的 hash
相反。