gpt4 book ai didi

java - 将不可修改的 View 发布到内部 map

转载 作者:行者123 更新时间:2023-11-30 03:06:42 24 4
gpt4 key购买 nike

我正在阅读 B. Goetz Java 并发实践,现在正在阅读有关委托(delegate)线程安全的部分。他提供了以下示例:

@Immutable
public class Point{
public final int x, y;

public Point(int x, int y){
this.x = x;
this.y = y;
}
}

@ThreadSafe
public class DelegatingVehicleTracker {

private final ConcurrentMap<String, Point> locations;
private final Map<String, Point> unmodifiableMap;

public DelegatingVehicleTracker(Map<String, Point> points){
locations = new ConcurrentHashMap<String, Point>(points);
unomdifiableMap = Collections.unmodifiableMap(locations);
}

public Map<String, Point> getLocations(){
return unmodifiableMap;
}

public Point getLocation(String id){
return locations.get(id);
}

public void setLocation(String id, int x, int y){
if(locations.replace(id, new Point(x, y)) == null)
throw new IllegalArgumentException("invalid vehicle id: " + id);
}

}

他这么说

if thread A calls getLocations and thread B later modifies the locations of some of the point, those changes are reflected in the Map returned to thread A. As we remarked earlier, this can be a benefit (more up-to-date data) or a liability (potentially inconsistent view of the fleet), depending on your requirement.

我不明白这个缺点。为什么舰队的视野会变得不一致。所有对象都是不可变的。

最佳答案

所有对象并非都是不可变的:locations不是,所以 unmodifiableMap 也不是.

问题可能没有您想象的那么棘手。自 locations是线程安全的,并且 unmodifiableMap除了对 locations 的(不可变)引用之外,没有任何状态,不存在奇怪的内存可见性问题。

奇怪的是,对于此类消费者来说,getLocation看起来它可以“神奇地”改变任何给定线程的值。换句话说,如果一个线程执行以下操作:

Point p1 = tracker.getLocation("vehicle1");
Point p2 = tracker.getLocation("vehicle1");
assert p1.equals(p2);

...那么该代码的编写者可能会对其失败感到惊讶。毕竟,我只是同一辆车获得了两次积分,并没有调用 setLocation他们之间——那么位置怎么会改变呢?答案当然是某个名为 setLocation其他线程。 ,我看到两次调用 getLocation 之间发生了变化.

上面的例子显然有点愚蠢,但不那么愚蠢的例子也不难想象。例如,假设您的应用程序想要对车队进行快照,并且假设两辆卡车不能同时位于同一地点。这是物理世界中的合理假设,但这不是您的应用程序可以做出的假设,因为在调用 getLocation 之间,一辆卡车可能已移动到另一辆卡车的位置。 :

Thread1 (taking a snapshot)             Thread2 (updating locations)
setLocation("truckA", 10, 10);
setLocation("truckB", 20, 20);
p1 = getLocation("truckA") // (10, 10)
setLocation("truckA", 5, 10);
setLocation("truckB", 10, 10);
p2 = getLocation("truckB") // (10, 10)
assert !p1.equals(p2); // fails

正如简介中提到的,这本质上并不是坏事;这完全取决于您的应用程序的需求和期望。

关于java - 将不可修改的 View 发布到内部 map ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34585651/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com