发生了一些我不确定应该可行的事情.显然它是,因为我已经看过了,但我需要找到根本原因而且我希望你们都能提供帮助.
我们有一个查找纬度和经度的邮政编码系统.我们不是每次都访问它,而是将结果缓存在廉价的内存中HashTable缓存中,因为邮政编码的纬度和长度往往比我们发布的更少.
无论如何,哈希被一个具有"get"和"add"方法的类所包围,这两个方法都是同步的.我们以单身形式访问此类.
我并不是说这是最好的设置,但它就是我们所处的位置.(我计划更改为尽快将Map包装在Collections.synchronizedMap()中.)
我们在多线程环境中使用此缓存,其中我们为2个拉链进行2次调用(因此我们可以计算两者之间的距离).这些有时几乎同时发生,因此两个调用很可能同时访问地图.
就在最近,我们遇到了两个不同邮政编码返回相同值的事件.假设初始值实际上是不同的,有没有办法将值写入Map会导致为两个不同的键写入相同的值?或者,2"获取"是否有任何方式可以交叉电线并意外返回相同的值?
我唯一的另一个解释是初始数据已损坏(错误的值),但似乎不太可能.
任何想法,将不胜感激.谢谢,彼得
(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; } }
Vladimir Dyu.. 8
代码看起来正确.
唯一的问题是lat和lon是包可见的,因此对于相同的包代码可以使用以下内容:
LatLongPair llp = InMemoryGeocodingCache.getInstance().get(ZIP1); llp.lat = x; llp.lon = y;
这显然会修改缓存中的对象.
所以也让lat和lon决赛.
PS由于您的密钥(zip-code)是唯一且小的,因此无需在每个操作上计算哈希值.使用TreeMap(包装到Collections.synchronizedMap()中)更容易.
PPS实用方法:为两个线程编写测试,在永不停止的循环中执行put/get操作,在每次获取时验证结果.你需要一台多CPU机器.
代码看起来正确.
唯一的问题是lat和lon是包可见的,因此对于相同的包代码可以使用以下内容:
LatLongPair llp = InMemoryGeocodingCache.getInstance().get(ZIP1); llp.lat = x; llp.lon = y;
这显然会修改缓存中的对象.
所以也让lat和lon决赛.
PS由于您的密钥(zip-code)是唯一且小的,因此无需在每个操作上计算哈希值.使用TreeMap(包装到Collections.synchronizedMap()中)更容易.
PPS实用方法:为两个线程编写测试,在永不停止的循环中执行put/get操作,在每次获取时验证结果.你需要一台多CPU机器.
为什么会发生这种情况很难说.更多代码可以帮助.
你应该只是使用ConcurrentHashMap.一般来说,这比同步Map更有效.您不同步对它的访问,它在内部处理它(比您更有效).