我很好奇这个缓存想法是否能保证工作:
@RequiredArgsConstructor @Getter class CacheEntry {
static CacheEntry get(String string, int start) {
int hash = string.hashCode() ^ start; // or something better
int index = hash & (cache.length-1);
CacheEntry result = cache[index];
if (result!=null && result.matches(string, start)) return result;
result = new CacheEntry(string, start, computeSomething(string, start));
cache[index] = result;
return result;
}
private boolean matches(String string, int start) {
if (string.equals(this.string)) return false;
if (start == this.start) return false;
return true;
}
private static ImmutableSomething computeSomething(String string, int start) {
...
}
private static final CacheEntry[] cache = new CacheEntry[256];
private final String string;
private final int start;
private final ImmutableSomething something;
}注释来自隆布克。想象一下每个人的名字都是怎么说的。
目标是保存对computeSomething的调用,并将分配最小化。
缓存既不是同步的,也不是线程本地的。不能保证一个线程会看到另一个线程所做的更新。这是可以接受的。也不能保证一个线程不会覆盖另一个线程的条目。这也可以接受。
在一个小的基准测试中,我编写了它,与明智的缓存替代方案相比,它会导致一个很好的加速。我担心的是正确性:线程是否会看到无效的条目(例如,包含错误something的条目)?
发布于 2014-09-14 16:44:43
只要CacheEntry是一个合适的不可变对象(而不仅仅是一个有效的不可变对象),它就能工作。这是因为不需要同步就可以安全地发布不可变对象,并且对象引用分配是原子的。
换句话说,如果CacheEntry不是完全不可变的,这是不安全的,因为使用者线程可能会看到一个未完全构造的对象。另外,如果缓存的是赋值不是原子的原语类型(double,long),则使用者线程可以看到垃圾(赋值的一半)。
编辑
根据Java并发在实践中的应用,在下列情况下,可以不同步地安全地发布对象:
final。this关键字在构造过程中不会转义)https://stackoverflow.com/questions/25835354
复制相似问题