使用ConcurrentMap.replace点下面是从Java并发摘录实践:什么是在这个例子中
public class DelegatingVehicleTracker {
private final ConcurrentMap<String, Point> locations;
private final Map<String, Point> unmodifiableMap;
public DelegatingVehicleTracker(final Map<String, Point> points) {
this.locations = new ConcurrentHashMap<>(points);
this.unmodifiableMap = Collections.unmodifiableMap(this.locations);
}
public Map<String, Point> getLocations() {
return unmodifiableMap;
}
public Point getLocation(final String id) {
return locations.get(id);
}
public void setLocation(final String id, final int x, final int y) {
if (null == locations.replace(id, new Point(x, y))) {
throw new IllegalArgumentException("Invalid vehicle name: " + id);
}
}
}
我的问题是关于它使用ConcurrentMap.replace
的setLocation
方法。此方法的JavaDoc说它等价于:
if (map.containsKey(key)) {
return map.put(key, value);
} else return null;
除了该操作是以原子方式执行的。
如果我们不使用原子版本,会出现什么问题。一种可能性是一个线程看到映射包含一个给定的键,并且在它为该键放置一个新值之前,另一个线程删除该键 - 值对,但由于示例中的类不允许移除,所以这不会发生。
另一种可能性是两个线程试图用不同的值替换相同的密钥。在这种情况下,一个线程可能不会返回正确的先前值,但在此示例中我们不关心之前的值,方法setLocation
返回void
。
因此,似乎该方法可以被重写而没有replace
。这就是我的问题。在书中同一类的后续版本中,与上述版本几乎相同,方法setLocation
不使用replace
,只是containsKey
,我在想这是否会影响线程安全。