【发布时间】:2008-10-28 18:31:19
【问题描述】:
发生了一些我不确定是否可能发生的事情。显然是这样,因为我已经看到了,但我需要找到根本原因,希望大家能提供帮助。
我们有一个系统可以查找邮政编码的纬度和经度。我们不是每次都访问它,而是将结果缓存在一个廉价的内存中 HashTable 缓存中,因为邮政编码的纬度和经度往往比我们发布的变化少。
无论如何,散列被一个类包围,该类具有同步的“get”和“add”方法。我们作为单例访问这个类。
我并不是说这是最好的设置,但它就是我们所处的位置。 (我计划尽快将地图包装在 Collections.synchronizedMap() 调用中。)
我们在多线程环境中使用此缓存,其中线程 2 调用 2 个 zip(因此我们可以计算两者之间的距离)。这些有时几乎同时发生,因此两个调用很可能同时访问地图。
就在最近我们发生了一个事件,两个不同的邮政编码返回相同的值。假设初始值实际上不同,有没有办法将值写入 Map 会导致为两个不同的键写入相同的值?或者,有什么方法可以让 2 个“gets”跨线并意外返回相同的值?
我唯一的其他解释是初始数据已损坏(错误值),但这似乎不太可能。
任何想法将不胜感激。 谢谢, 彼得
(PS:如果您需要更多信息、代码等,请告诉我)
public class InMemoryGeocodingCache implements GeocodingCache
{
private Map cache = new HashMap();
private static GeocodingCache instance = new InMemoryGeocodingCache();
public static GeocodingCache getInstance()
{
return instance;
}
public synchronized LatLongPair get(String zip)
{
return (LatLongPair) cache.get(zip);
}
public synchronized boolean has(String zip)
{
return cache.containsKey(zip);
}
public synchronized void add(String zip, double lat, double lon)
{
cache.put(zip, new LatLongPair(lat, lon));
}
}
public class LatLongPair {
double lat;
double lon;
LatLongPair(double lat, double lon)
{
this.lat = lat;
this.lon = lon;
}
public double getLatitude()
{
return this.lat;
}
public double getLongitude()
{
return this.lon;
}
}
【问题讨论】:
-
我没有看到任何使用“实例”的东西。它有什么用?此外,如果你制作了缓存“Map
”,你在做什么会更清楚。 -
我会非常仔细地检查调用 InMemoryGeocodingCache.add 的所有内容。
-
如果 LatLongPair 是真正不可变的(没有设置器),您应该将 lat 和 lon 设为最终值。从安全发布/java 内存模型的并发角度来看,这是有意义的。
标签: java multithreading collections concurrency hashmap