读书人

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

发布时间: 2014-01-19 01:28:51 作者: rapoo

【坑】自己山寨缓存出现的坑自己踩
就在前两天,在编写一段业务逻辑的时候,考虑到数据库中的数据值是固定的,为了提高效率,自己做了一个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等等


读书人网 >编程

热点推荐