开发者社区> 问答> 正文

多线程情况下不使用同步对同一个MAP的并发读写问题

假设有以下场景:
某一个业务要求,定时的从数据库中取出一批数据放入一个hashmap中。
有多个线程对这个Map进行读操作。
每过一段时间(如3分钟),都会对这个Map进行修改(put or remove
该场景对数据的一致性没有非常严格的要求。
如何能够在不使用同步的情况下,对这个Map进行安全的操作呢?(例如不用concurrentHashMap,或Collections.synchronizedMap
我的想法是,每次在需要修改Map的时候,可以创建一个旧Map的副本,对副本进行修改后,再替换原先的·Map·
例如:
Map newMap = oldMap.clone(); //或者用new HashMap().putall(oldMap)来创造副本
newMap.put / remove ..... //修改map
oldMap = newMap; //替换上去
这样就不会因为对同一个map的并发读写而导致快速迭代失败。有没有大神看看这样有什么潜在的问题,比如GC。请不吝赐教
(
jdk 1.6 api hashMap
在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器本身的 remove 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒在将来不确定的时间发生任意不确定行为的风险。
)

展开
收起
蛮大人123 2016-03-19 11:45:45 4124 0
1 条回答
写回答
取消 提交回答
  • 我说我不帅他们就打我,还说我虚伪

    尽量用同步,可以避免很多的问题,同步:
    ` synchronizedMap
    public static Map synchronizedMap(Map m)`

    返回由指定映射支持的同步(线程安全的)映射。为了保证按顺序访问,必须通过返回的映射完成 所有对底层实现映射的访问。
    在返回映射的任意 collection 视图上进行迭代时,用户必须手工在返回的映射上进行同步:
     Map m = Collections.synchronizedMap(new HashMap());
              ...
          Set s = m.keySet();  // Needn't be in synchronized block
              ...
          synchronized(m) {  // Synchronizing on m, not s!
              Iterator i = s.iterator(); // Must be in synchronized block
              while (i.hasNext())
                  foo(i.next());
          }
    不遵从此建议将导致无法确定的行为。
    如果指定映射是可序列化的,则返回的映射也将是可序列化的。
    参数:
        m - 被“包装”在同步映射中的映射。 
    返回:
        指定映射的同步视图。 
    2019-07-17 19:07:55
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
多IO线程优化版 立即下载
用户态高速块缓存方案 立即下载
低代码开发师(初级)实战教程 立即下载

相关实验场景

更多