首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >这个缓存线程安全吗?

这个缓存线程安全吗?
EN

Stack Overflow用户
提问于 2014-09-14 16:20:20
回答 1查看 119关注 0票数 2

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

代码语言:javascript
运行
复制
@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的条目)?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-14 16:44:43

只要CacheEntry是一个合适的不可变对象(而不仅仅是一个有效的不可变对象),它就能工作。这是因为不需要同步就可以安全地发布不可变对象,并且对象引用分配是原子的。

换句话说,如果CacheEntry不是完全不可变的,这是不安全的,因为使用者线程可能会看到一个未完全构造的对象。另外,如果缓存的是赋值不是原子的原语类型(doublelong),则使用者线程可以看到垃圾(赋值的一半)。

编辑

根据Java并发在实践中的应用,在下列情况下,可以不同步地安全地发布对象:

  • 其状态不能在施工后修改。
  • 它的所有字段都声明为final
  • 它的构造是正确的( this关键字在构造过程中不会转义)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25835354

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档