Java:与垃圾收集器赛跑

标签 java garbage-collection race-condition

我已经实现了 Object像这样缓存:

// Dictionary with weak keys & values
private Map<Object, WeakReference<Object>> cache = new WeakHashMap<>();

private Object checkCache(Object obj) {

    // If it's in the cache, returned the cached copy.
    if (cache.containsKey(obj)) return cache.get(obj).get();

    // Store it in, and return it.
    cache.put(obj, new WeakReference<>(obj));
    return obj;
}

想象以下竞争条件场景:

  1. cache.containsKey(obj)返回true
  2. 垃圾收集器启动并获取缓存中的对象。
  3. null已返回。

问题是:

  • 这真的会发生吗? AFAIK GC 可以在任何时间启动。
  • 是否可以针对单个方法调用禁用 Java GC? synchronized似乎并不能阻止 GC。
  • 有任何解决方法吗?

提前致谢!

最佳答案

Can this really happen?

是的。

Can Java GC be disabled for a single method call?

没有。

Are there any work-arounds?

是:您尝试从缓存中检索对象(如果该对象仍在缓存中,则建立强引用),如果该引用为 null,则将其添加到缓存中:

WeakReference<Object> ref = cache.get(obj);
Object cached = (ref != null) ? ref.get() : null;
if (cached != null) {
    return cached;
}
else {
    cache.put(obj, new WeakReference(obj));
    return obj;
}

您仍然需要同步该方法,否则可能有两个线程同时更新缓存(结果 update race 将是 least of your worries )。

关于Java:与垃圾收集器赛跑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24109126/

相关文章:

java - ArrayList 上的递归二分查找

.net - 当 .NET 垃圾收集压缩堆时, "Allocate Bytes"性能计数器是否更新?

java - Java 中的 volatile 和线程安全

c# - 两个相同条件语句之间的锁定是好的模式吗?

java - 无法生成大素数

java - 将输入保存到文件

java - Android App 无法启动 Activity ComponentInfo

java - 如果不是父对象,那么在 super.finalize() 方法之后 GC 会在父对象上清除什么?

Java 字符串内存泄漏 II

python - 我怎样才能避免这种竞争情况?