我正在阅读这篇博文.
作者正在谈论在多线程环境中打破hashCode()in String.
有了:
public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31*h + val[off++];
}
hash = h;
}
return h;
}
Run Code Online (Sandbox Code Playgroud)
变成:
public int hashCode() {
if (hash == 0) {
int off = offset;
char val[] = value;
int len = count;
int …Run Code Online (Sandbox Code Playgroud) 一些Guava内部类型,例如AbstractMultiset,有这样的模式:
private transient Set<E> elementSet;
@Override
public Set<E> elementSet() {
Set<E> result = elementSet;
if (result == null) {
elementSet = result = createElementSet();
}
return result;
}
Set<E> createElementSet() {
return new ElementSet();
}
Run Code Online (Sandbox Code Playgroud)
我们的想法是延迟创建集合视图(elementSet(),entrySet()),直到实际需要它们为止.进程周围没有锁定,因为如果两个线程同时调用elementSet(),则可以返回两个不同的值.编写该elementSet字段会有竞争,但由于写入引用字段在Java中始终是原子的,因此谁赢得竞争并不重要.
但是,我担心Java内存模型在这里内联的内容.如果createElementSet()和ElementSet的构造函数都被内联,似乎我们可以得到这样的东西:
@Override
public Set<E> elementSet() {
Set<E> result = elementSet;
if (result == null) {
elementSet = result = (allocate an ElementSet);
(run ElementSet's constructor);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
这将允许另一个线程观察到一个非null但未完全初始化的值 …
为什么说不可变对象使用惰性哈希码初始化呢?对于可变对象也是如此,我们只能在需要时才计算哈希码,这会导致延迟初始化吗?