`
cheng.xinwei
  • 浏览: 78436 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【坑】自己山寨缓存出现的坑自己踩

    博客分类:
  • JAVA
阅读更多
    就在前两天,在编写一段业务逻辑的时候,考虑到数据库中的数据值是固定的,为了提高效率,自己做了一个Map的缓存,大致代码如下。
   
      //缓存类
      @service
      public class CacheService{
        private Map<String,List<Object>> cache = new Concurrenthashmap<>();
  
        public List<Object> get(String key){
           return cache.get(key);
        }

        public void put(String key, List<Object> list){
           cache.put(key,list);
        }

        public void del(String key){
           cache.remove(key);
        }
      }
    


    如上代码,乍看下来不会有什么问题,功能也可以正常实现。但是其实他是极其不安全的。
    为什么怎么说?当我们其他的service把这个cache依赖注入的时候,如果要执行如下代码。执行之后会有什么问题?

   
       List<Object> list = cacheService.get("A");
       for(int i = list.size()-1 ; i >=0 ; i -- ){
          if(needRemove){
             list.remove(i);
          }
       }
    


    执行完之后,当下次另外一个地方也需要去取cacheService中的“A”的时候,会发现LIST中元素的内容变少了,原因是,cacheService在放入和取出的时候都没有做copy,没有做copy导致的外部获取的list和内部cacheService中list的地址是同一个,外部修改的话,会同时修改掉内部的list的元素。这样的做法是极其不安全的。所以,只需要在get 和 put方法中添加collections.copy() 就不会出现如上的问题了。同样的问题还会出现在其他类似的集合中。

    注:可以依赖一些代码规范检查的服务器或者插件,他们也可以帮你检查出类似的问题,比如获取数组的时候,需要clone等等
  

   
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics