在多线程情况下,不使用同步,对同一个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。因此,面对并发的修改,迭代器很快就会完全失败,而不冒在将来不确定的时间发生任意不确定行为的风险。
)

创建一个旧MAP的副本,对副本进行修改后,再替换原先的MAP
这样做还是可能出现问题的,数据还是有可能出错,同步才是最安全的办法。

尽量用同步,可以避免很多的问题,同步:

 synchronizedMap

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> 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 - 被“包装”在同步映射中的映射。 
    返回:
        指定映射的同步视图。 



除了内存使用量会增加,我认为没问题。
不知道是何时如何取得新MAP的新迭代器,其他不好判断。