我有一个Map对象,它对应于存储在File中的键值对 .
private static Map myMap;
这个Map对象有一个管理器类,它有一个方法getMap(),它将对象返回给调用者 .
public static Map getMap()
它还有一个synchronized方法saveMap(),它将内容保存回File
public static synchronized void saveMap(Map map)
问题是,有些线程获取Map对象但不想保存,即它们不调用saveMap() .
假设 thread1 获取 Map 对象并对其进行修改,即向 Map 添加键值对 . key1=value1 并在任务完成后,从 Map 中删除此键值对 . 在中间有另一个线程 thread2 ,它将另一个键值对添加到 Map key2=value2 并在 thread1 实际从 Map 中删除 key1 之前保存它 . 这会导致key1 = value1和key2 = value2都保存到文件中 . 这不是我想要的 .
我怎样才能克服这种情况?我正在考虑用类似的方法修改getMap()方法
public Map getMap(boolean readonly) {
if (readonly)
return myMap.clone();
return myMap;
}
这会解决我的问题吗?
注意:我不想使用互斥锁并锁定Map对象,因为我有长时间运行的进程会阻塞其他线程 .
1 回答
我会做两件事之一 .
第一个,也就是我推荐的那个,是不要通过 Map 的副本 . 除了不使用同步对象的多线程问题之外,没有办法确保不会丢失/覆盖交叉获取/保存的值 .
在你的manager类中,删除了getMap()和saveMap(),并用getValue()和setValue()替换它们 . 我会使这些方法同步,或用ConcurrentMap替换Map . 这样你就不会有人坚持整个 Map 的实例 .
第二个选项是用Hashtable替换Map . 这是同步和线程安全的,但速度较慢 . 那会解决你的一些问题,但不是全部问题 . 您仍然对代码周围的 Map 有松散的引用 .