zoukankan      html  css  js  c++  java
  • 使用Dictionary做缓存的一些问题.

    在实际开发过程中,Dictionary是一种经常被用来做缓存的数据结构,既然是用来做缓存,那么不可避免的就要涉及到多线程的问题,如何来合理的使用,这是一个问题,这个问题与实际业务场景有很大关系,通常来说,会有这么几种场景

    1, 一次性写入,不再改变

    2, 存在写入与删除

    对于缓存来说,永远是读操作占了大部分,因此,必须要确保对于读来说,不会影响并发,这是首要的原则,对于那种在读的时候需要lock的必须否定,对于第一种场景,没什么可说的,直接使用Dictionary就行,Dictionary在内容不变的情况下,对于读操作是可以并发的,并且这种情况下读性能是最好的。

    对于第二种场景来说,又要做区分,需要根据缓存列表的预估长度以及写操作频繁度来选择,

    如果预估长度不大或者写操作不频繁,建议通过“不变列表”模式来实现,具体来说,在写操作的代码中,这样写

     1 //_lock为一个静态object,用来做lock操作
     2             //_dict为静态缓存的Dictionary对象
     3             lock(_lock)
     4             {
     5                 //通过ToDictionary浅拷贝出一个新的Dictionary对象
     6                 //这样可以保证原先的_dict对于读操作“不变”,使读操作不收任何并发影响
     7                 var copyDict =_dict.ToDictionary((kv) => kv.Key,(kv)=>kv.Value);
     8                 //这里做新增删除的动作
     9                 copyDict["key"] = "value";
    10                 //修改完成后重新为静态缓存赋值
    11                 _dict = copyDict;
    12             }

    这就是所谓的“不变列表”模式,从这里也可以看出,如果列表长度很大的话,其实每次执行浅拷贝的动作都会有不少的耗时,这个耗时是随着列表的长度线性增长的,这就是为什么这种模式适用于“预估长度不大或者写操作不频繁”这种场景。

    那如果预估长度很大或者写操作很频繁怎么办呢,这个使用就要用到框架中的并行字典了,也就是ConcurrentDictionary,这个是线程安全的字典类,因此可以像单线程操作一样去使用,它的内部已经做了多线程的处理了,唯一的缺点是,在读的时候,由于内部依然会有锁的动作,是不如“不变列表”模式的性能高的。

    以上就是使用Dictionary做缓存时要考虑的问题

  • 相关阅读:
    StringBuider 在什么条件下使用效率更高?
    Hibernate 与 Mybatis 如何共存?打破你的认知!
    牛逼!OpenJDK 源码要迁移到 GitHub 了!
    别在网上乱找代码了,找了一段代码突然爆了!!!
    8 条关于 Web 前端性能的优化建议
    关于 equals 和 hashCode,看这一篇真的够了!
    Python web之Python如何调用REST服务?
    ArcGIS Server如何发布gp服务
    ArcGIS坐标单位转换(米和度分秒之间是如何转换的?)
    ArcGIS MapServer和FeatureServer的区别
  • 原文地址:https://www.cnblogs.com/rhwleo/p/6883165.html
Copyright © 2011-2022 走看看