Demo code结束后,有一句话没太理解:“PlublishingVehicleTracker是线程安全的,但是如果它在车辆位置的有效值上施加了任何约束,那么就不再是线程安全的”,SafePoint本身已经通过内置锁保证了对象内数据的线程安全,那么即使在set方法内加入了一些判断location位置的有效性代码也不会导致线程不安全吧。求指点!
代码如下:
@ThreadSafe
public class PublishingVehicleTracker {
private final Map<String, SafePoint> locations;
private final Map<String, SafePoint> unmodifiableMap;
public PublishingVehicleTracker(
Map<String, SafePoint> locations) {
this.locations
= new ConcurrentHashMap<String, SafePoint>(locations);
this.unmodifiableMap
= Collections.unmodifiableMap(this.locations);
}
public Map<String, SafePoint> getLocations() {
return unmodifiableMap;
}
public SafePoint getLocation(String id) {
return locations.get(id);
}
public void setLocation(String id, int x, int y) {
if (!locations.containsKey(id))
throw new IllegalArgumentException(
"invalid vehicle name: " + id);
locations.get(id).set(x, y);
}
}
@ThreadSafe
public class SafePoint {
@GuardedBy("this") private int x, y;
private SafePoint(int[] a) { this(a[0], a[1]); }
public SafePoint(SafePoint p) { this(p.get()); }
public SafePoint(int x, int y) {
this.x = x;
this.y = y;
}
public synchronized int[] get() {
return new int[] { x, y };
}
public synchronized void set(int x, int y) {
this.x = x;
this.y = y;
}
}
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
正好有这本书,重新看了下,对这最后两句我的理解是在强调虽然PublishingVehicleTracker和SafePoint本身都是threadsafe的,但是PublishingVehicleTracker发布出来的SafePoint是可变的,因此如果使用场景里需要基于PublishingVehicleTracker发布出来的Location(即SafePoint)做一些逻辑判断或者其他的操作时,结果可能是有问题的。
例如,如果A线程对通过getLocations获取的Map做遍历的同时,B线程通过setLocation方法修改其中的一个SafePoint值,那么A线程的处理结果就有了问题。
写了一个A线程内处理过程的样例代码,不一定确切,仅供参考: