Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.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 Volatile HashMap与ConcurrentHashMap_Java_Caching_Concurrency_Hashmap - Fatal编程技术网

Java Volatile HashMap与ConcurrentHashMap

Java Volatile HashMap与ConcurrentHashMap,java,caching,concurrency,hashmap,Java,Caching,Concurrency,Hashmap,我有一个缓存类,它包含一个volatile HashMap,用于存储缓存项 我很好奇将volatile HashMap更改为ConcurrentHashMap会产生什么后果 我会获得性能提升吗?此缓存是只读缓存 最好的选择是什么?只是HashMap?缓存正在按间隔填充。首先,您似乎不了解volatile关键字的作用。它确保如果声明的变量volatile持有的引用值发生更改,其他线程将看到它,而不是缓存副本。访问HashMap 考虑到这一点,并且您说HashMap是只读的。。。您当然不需要使用任何

我有一个缓存类,它包含一个
volatile HashMap
,用于存储缓存项

我很好奇将
volatile HashMap
更改为
ConcurrentHashMap
会产生什么后果

我会获得性能提升吗?此缓存是只读缓存


最好的选择是什么?只是HashMap?缓存正在按间隔填充。

首先,您似乎不了解
volatile
关键字的作用。它确保如果声明的变量
volatile
持有的引用值发生更改,其他线程将看到它,而不是缓存副本。访问
HashMap

考虑到这一点,并且您说
HashMap
是只读的。。。您当然不需要使用任何提供线程安全的工具,包括
ConcurrentHashMap

编辑以添加:上次编辑时,您现在说“缓存正在按一定间隔填充”

那不是只读的,是吗

如果要让线程在编写(更新现有的HashMap)时读取它,那么应该使用
ConcurrentHashMap
,是的


如果您正在填充一个全新的
HashMap
,然后将其分配给现有变量,那么您可以使用
volatile

您说缓存是只读的,但更新的间隔似乎是矛盾的

如果整个缓存每隔一段时间更新,我会继续使用volatile。 volatile将确保安全发布更新的地图

public final class  Cache
{
   private volatile Map<?,?> cache;

   private void mapUpdate() {
      Map<?,?> newCache = new HashMap<>();

      // populate the map

      // update the reference with an immutable collection
      cache = Collections.unmodifiableMap(newCache);
   }
}
公共最终类缓存
{
私有易失性映射缓存;
私有void映射更新(){
Map newCache=newhashmap();
//填充地图
//使用不可变集合更新引用
cache=Collections.unmodifiableMap(newCache);
}
}
如果间隔更新正在修改相同的缓存,那么您可能希望使用ConcurrentHashMap,或者复制映射、更新副本和更新引用

public final class  Cache
{
   private volatile Map<?,?> cache;

   private void mapUpdate() {
      Map<?,?> newCache = new HashMap<>(cache);

      // update the map

      // update the reference with an immutable collection
      cache = Collections.unmodifiableMap(newCache);
   }
}
公共最终类缓存
{
私有易失性映射缓存;
私有void映射更新(){
Map newCache=newhashmap(缓存);
//更新地图
//使用不可变集合更新引用
cache=Collections.unmodifiableMap(newCache);
}
}

我的web应用程序也有类似的用例。我在内存缓存中使用哈希映射。用例如下所示-

  • 一个用户请求进入,首先使用输入键检查缓存中是否存在记录。这是在add方法中完成的
  • 如果对象不存在,则会在缓存中插入新记录
  • 类似地,在remove方法中,首先使用键检查缓存中是否存在记录,如果找到,则删除该记录
  • 我想确保两个线程同时执行一个在add方法上,另一个在remove方法上。这种方法能确保它们在缓存中看到最新的数据吗?若我并没有错,那个么同步方法将负责线程安全,而as volatile负责可见性

    private volatile HashMap<String,String> activeRequests = new HashMap<String,String>();
    public synchronized boolean add(String pageKey, String space, String pageName) {
        if (!(activeRequests.get(pageKey) == null)) {
           return false;
        }
        activeRequests.put(pageKey, space + ":" + pageName);
        return true;
    }
    
    public synchronized void remove(String pageKey) {       
        if(!(activeRequests.get(pageKey) == null))
            activeRequests.remove(pageKey);
        }
    
    private volatile HashMap activeRequests=new HashMap();
    公共同步布尔添加(字符串pageKey、字符串空格、字符串pageName){
    if(!(activeRequests.get(pageKey)=null)){
    返回false;
    }
    activeRequests.put(pageKey,空格+:“+pageName);
    返回true;
    }
    公共同步无效删除(字符串pageKey){
    if(!(activeRequests.get(pageKey)=null))
    activeRequests.remove(pageKey);
    }
    
    如果它是只读的,您需要。。。两者都不是。
    HashMap
    上的
    volatile
    意味着您在获取/设置
    HashMap
    对象时跨越了内存障碍。当您从中添加或删除内容时,它不会执行任何操作map@BrianRoach你会使用什么?这就是我使用volatile的原因,有一个后台线程从文件中读取并生成一个新的hashmap,然后分配给缓存。我正计划改变设计,这就是我为什么问的原因。不过你回答了这两个问题。谢谢。实际上,你可以使用
    volatile
    来确保人们看到最新的元素(基本上与获取“volatile”数组元素的方式相同),这只是a)性能差,b)复杂,c)在添加数据时无助于内部竞争条件,d)非常愚蠢。但这是可行的!;)@Voo你会用什么?或者你会怎么做?@Darth注意到我的评论是关于使用volatile在hashmap上添加条目并确保它们是可见的,而不是你想做的。b2t:我只想先使用
    ConcurrentHashmap
    ——它就是为此而构建的。如果我在映射中遇到了高性能瓶颈,我会使用Cliff的无锁HashMap实现,在任何情况下都会使用后台线程从缓存中删除旧条目。内存开销更小,没有大的峰值,性能仍然很好。如果您真的只想每X分钟创建一个新缓存,Michael的解决方案会很好。@BrianRoach我没有收到您关于只读映射不需要线程安全的评论。有些线程必须在某个点将一些数据放在映射中,如果在映射到其他线程之后添加了这些数据,那么就有麻烦了。我会考虑保持高速缓存字段非易失性。由于Collections.unmodifiableMap,将安全发布指向新版本地图的最终字段链接。在某个时刻,所有线程都将获取新版本的缓存映射。通常(但不总是!)缓存是否不是立即可用,而是在几毫秒内可用并不重要。并使该字段非易失性,从而稍微提高CPU缓存性能。