gpt4 book ai didi

java - 这个缓存线程安全吗?

转载 作者:行者123 更新时间:2023-11-30 08:20:43 25 4
gpt4 key购买 nike

我很好奇这个缓存想法是否能保证有效:

@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;
}

注释来自lombok .试想一下,每个人都按照其名称进行操作。

目标是节省对 computeSomething 的调用,同时最大限度地减少分配。

缓存既不是同步的也不是线程本地的。不能保证一个线程会看到另一个线程完成的更新。这是可以接受的。也不能保证一个线程不会覆盖另一个线程的条目。这也是可以接受的。

在我写的一个小型基准测试中,与 sane caching alternatives 相比,它带来了不错的加速。 .我关心的是正确性:线程看到无效条目(例如,包含错误的 something)的情况是否会发生?

最佳答案

只要 CacheEntry 是一个适当的不可变对象(immutable对象)(而不是仅仅有效的不可变对象(immutable对象)),这就可以工作。这是因为不可变对象(immutable对象)可以在没有同步的情况下安全地发布,并且对象引用分配是原子的。

换句话说,如果 CacheEntry 不是完全不可变的,那将是不安全的,因为消费者线程可能会看到一个未完全构造的对象。此外,如果缓存的是原始类型,其分配不是原子的(doublelong),则使用者线程可能会看到垃圾(分配的值减半)。

编辑:
根据Java Concurrency in Practice ,如果满足以下条件,则无需同步即可安全地发布对象:

  • 其状态在构造后不能修改
  • 它的所有字段都被声明为final
  • 构造正确(this 关键字在构造过程中没有转义)

关于java - 这个缓存线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25835354/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com