首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WeakHashMap和ReentrantReadWriteLock

WeakHashMap和ReentrantReadWriteLock
EN

Stack Overflow用户
提问于 2019-04-09 03:39:48
回答 2查看 155关注 0票数 1

我使用WeakHashMap和ReentrantReadWriteLock实现了一个缓存,代码如下所示:

代码语言:javascript
复制
class Demo<T, K> {

    private final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock();

    private final Map<T, K> CACHE = new WeakHashMap<>();

    public K get(T t) {
        ReentrantReadWriteLock.ReadLock readLock = LOCK.readLock();
        ReentrantReadWriteLock.WriteLock writeLock = LOCK.writeLock();

        readLock.lock();
        if(CACHE.containsKey(t)){

            //-- question point --

            K result = CACHE.get(t);
            readLock.unlock();
            return result;
        }
        readLock.unlock();

        K result = // find from db;

        writeLock.lock();
        CACHE.put(t,result);
        writeLock.unlock();

        return result;
    }
}

我的问题是,当gc在if(CACHE.containsKey(t))之后执行,但在K result = CACHE.get(t);之前使用读锁执行,并导致if(CACHE.containsKey(t))为真,但K result = CACHE.get(t);为空。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-09 03:57:20

您的ReentrantReadWriteLock无法控制WeakHashMap对于垃圾收集器的行为。

用于WeakHashMap状态的类javadoc

WeakHashMap类的行为在一定程度上取决于垃圾收集器的操作,因此几个熟悉的(尽管不是必需的) Map不变量对于这个类不成立。因为垃圾收集器可以在任何时候丢弃键,所以WeakHashMap的行为可能就像一个未知的线程正在悄悄地删除条目一样。特别是,即使您在一个containsKey实例上同步并且不调用它的任何一个变量方法,随着时间的推移,size方法也有可能返回较小的值,对于isEmpty方法返回false,然后返回true用于 false 方法返回,以及稍后对于给定密钥返回E 222falseE 126,对于get方法返回给定密钥的值,但随后返回null,对于put方法返回null和remove方法返回以前在映射中出现的键的false,以及对键集、值集合和条目集的连续检查,以依次生成较小数量的元素。

换句话说,如果垃圾收集器在两个调用之间起作用(并且您没有对相应键的其他强引用),则containsKey调用可以返回true和后面的get返回false

您可以使用下面这样的小程序来验证这种行为

代码语言:javascript
复制
public class Example {
    public static void main(String[] args) throws Exception {
        WeakHashMap<Example, Integer> CACHE = new WeakHashMap<>();
        CACHE.put(new Example(), 2);
        if (CACHE.containsKey(new Example())) {
            System.gc();
            System.out.println("missing? " + CACHE.get(new Example()));
        }
    }

    @Override
    public int hashCode() {
        return 42;
    }

    @Override
    public boolean equals(Object obj) {
        return true;
    }
}

哪种指纹

代码语言:javascript
复制
missing? null
票数 2
EN

Stack Overflow用户

发布于 2019-04-09 03:56:02

然后您的代码将返回null。

如果这不是您想要的,只需执行get()调用并检查是否有非空结果。如果您担心返回null,那么在这里调用containsKey()是没有好处的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55584782

复制
相关文章

相似问题

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