Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在不影响性能的情况下,同时使java中几个工作进程的缓存失效_Java_Caching_Concurrency_Linkedhashmap - Fatal编程技术网

在不影响性能的情况下,同时使java中几个工作进程的缓存失效

在不影响性能的情况下,同时使java中几个工作进程的缓存失效,java,caching,concurrency,linkedhashmap,Java,Caching,Concurrency,Linkedhashmap,我正在创建自己的缓存对象,该对象将服务于多个线程,这是一个分配,因此不允许我使用存在的包和jar。我正试图找出如何同时使所有这些无效。 我有一个日期结构,它包含一组条目,其中键是一个整数,值是一个布尔值。当工作进程未命中时,它会将该值添加到其缓存中。 我还有几个其他线程更新这个数据结构,一旦它们更新了这个数据结构,它们就应该使拥有这个缓存的所有其他工作线程失效,只有当它们的缓存中有这个条目时 比如说 假设有两个工人 T1缓存有1,true T2缓存有3个,true 并且数据结构有1,true;2

我正在创建自己的缓存对象,该对象将服务于多个线程,这是一个分配,因此不允许我使用存在的包和jar。我正试图找出如何同时使所有这些无效。 我有一个日期结构,它包含一组条目,其中键是一个整数,值是一个布尔值。当工作进程未命中时,它会将该值添加到其缓存中。 我还有几个其他线程更新这个数据结构,一旦它们更新了这个数据结构,它们就应该使拥有这个缓存的所有其他工作线程失效,只有当它们的缓存中有这个条目时

比如说 假设有两个工人 T1缓存有1,true T2缓存有3个,true

并且数据结构有1,true;2、正确;3是的。现在更新程序更改为3,false。所以它应该检查T1,不做任何事情,应该检查T2,然后改变它。然而,这两个检查应该同时进行,因为如果我有一个 T1缓存有3个,true T2缓存有3个,true T1可能无效,而T2尚未无效,我们有一个不一致的行为

有什么想法吗? 我的缓存代码是

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

public class workerCache {
    @SuppressWarnings("rawtypes")
    LinkedHashMap cache;
    ReentrantLock lock;

    @SuppressWarnings("serial")
    public <T> workerCache(final int maxEntries) {
        this.lock = new ReentrantLock();

        this.cache = new LinkedHashMap<T, T>(maxEntries + 1) {
            @SuppressWarnings("rawtypes")
            protected boolean removeEldestEntry(Map.Entry eldest) {
                return size() > maxEntries;
            }
        };
    }

    @SuppressWarnings("unchecked")
    public <T> void setEntry(T key, T value) {

        lock.lock();
        try {
            cache.put(key, value);
        } finally {
            lock.unlock();
        }
    }

    public <T> void invalidateEntry(T key) {
        lock.lock();
        try {
            cache.remove(key);
        } finally {
            lock.unlock();
        }

    }

    @SuppressWarnings("unchecked")
    public <T> T get(T key) {
        lock.lock();
        try {
            return (T) this.cache.get(key);
        } finally {
            lock.unlock();
        }
    }
import java.util.LinkedHashMap;
导入java.util.Map;
导入java.util.concurrent.locks.ReentrantLock;
公营工人车{
@抑制警告(“原始类型”)
LinkedHashMap缓存;
可重入锁;
@抑制警告(“串行”)
公共workerCache(最终整数maxEntries){
this.lock=new ReentrantLock();
this.cache=新建LinkedHashMap(maxEntries+1){
@抑制警告(“原始类型”)
受保护的布尔重构(Map.Entry最早){
返回size()>maxEntries;
}
};
}
@抑制警告(“未选中”)
公共无效设置项(T键,T值){
lock.lock();
试一试{
cache.put(键、值);
}最后{
lock.unlock();
}
}
公共无效无效重试(T键){
lock.lock();
试一试{
缓存。删除(键);
}最后{
lock.unlock();
}
}
@抑制警告(“未选中”)
公共T获取(T键){
lock.lock();
试一试{
返回(T)this.cache.get(key);
}最后{
lock.unlock();
}
}

听起来你好像在想象三个线程“T1”、“T2”、“T3”都有自己的
workerCache
副本,它们需要保持同步。对吗

如果是这样,我会说这是一个问题。与其使用三个缓存(每个线程一个),不如在所有线程之间共享一个缓存

这样一来,每个人都会一直看到相同的数据b/c只有一个数据副本(因为只有一个缓存)。如果您从T1中使一个条目无效,那么每个人都会同时“看到”该无效—这是因为只有一个缓存

如果你有三个线程都在更新同一个密钥,那么最后一个进入缓存的线程将获胜。我不确定这是否是你的问题


我在哪里遇到了这个问题?

您的缓存体系结构排除了除全局锁定以外的任何东西来满足您的需求。重新设计缓存,并在重新设计时,消除当前缓存API引入的可能的完整性差距(如果值正确更改,会发生什么情况?instant get()返回值?)。这就是问题所在,我如何在更改后完全使所有数据无效?否则,我会发现,在您刚才描述的情况下,考虑责任倒置:更新程序不通知缓存,而是让缓存验证它们的条目对每个get()都有效。还要仔细考虑工作进程和缓存之间的可重复性-谁负责处理缓存未命中?谁控制条目的完整性?谁控制从条目派生的数据的完整性(也称为结果)?谢谢你的回答。如果工作人员将在每次get时更新缓存,这是否就像没有缓存一样,即,你将每一次命中都视为未命中!此外,工作人员是否有责任在未命中时更新其缓存?如果你的更新程序不提供fas,我假设更新程序应该控制entries的完整性t验证条目的方法,那么是的,它将违背目的-取决于实际数据的详细信息(数量、更改频率、条目检索成本)您需要找到一种允许快速条目验证的方法。最简单的方法可能是一个简单的版本计数器,用于限定整个缓存-副作用是任何更改都会使所有条目无效。如果不希望这样,您可以为每个条目找到一个版本,或者使用分区方案,其中每个分区都有一个版本。Th是一个有趣的解决方案。但是,它不是降低了缓存的有效性吗?如中所示,与3个线程共享此对象将导致线程前往内存中的某个位置访问此对象,而不是具有本地副本。可能我对内存和局部性的理解不正确。当您有多个线程时,内存局部性是一个问题竞争同一缓存线的读卡器。如果您有多个读卡器,那么它们可以拥有自己的处理器本地副本——这是处理器缓存和缓存失效工作方式的副作用。(我指的是在内核和socks之间以及在硬件上实现缓存失效。)“规模原则”