1
「Java併發實踐」本書有一個MonitorVehicleTracker
代碼示例,聲明爲線程安全。施工期間的線程安全
@ThreadSafe
public class MonitorVehicleTracker {
@GuardedBy("this") private final Map<String, MutablePoint> locations;
public MonitorVehicleTracker(Map<String, MutablePoint> locations) {
this.locations = deepCopy(locations);
}
public synchronized Map<String, MutablePoint> getLocations() {
return deepCopy(locations);
}
public synchronized MutablePoint getLocation(String id) {
MutablePoint loc = locations.get(id);
return loc == null ? null : new MutablePoint(loc);
}
public synchronized void setLocation(String id, int x, int y) {
MutablePoint loc = locations.get(id);
if (loc == null)
throw new IllegalArgumentException("No such ID: " + id);
loc.x = x;
loc.y = y;
}
private static Map<String, MutablePoint> deepCopy(Map<String, MutablePoint> m) {
Map<String, MutablePoint> result = new HashMap<String, MutablePoint>();
for (String id : m.keySet())
result.put(id, new MutablePoint(m.get(id)));
return Collections.unmodifiableMap(result);
}
}
但是讓我們考慮當構造locations
說法是deepCopy()
通話過程中修改被另一個線程。這可能導致ConcurrentModificationException
在迭代keySet()
時拋出。
那麼這是否意味着MonitorVehicleTracker
不是完全線程安全的?或線程安全只有在對象構造完成後纔出現,並且調用代碼負責確保在MonitorVehicleTracker
實例化期間locations
不會被修改?
正確; 'locations'的'Map'實現不是線程安全的,但是'MonitorVehicleTracker'是。 – erickson
這是否也適用於類不變量由於線程交錯而在構造期間被破壞的情況? –
@PavloViazovskyy我會這麼說 –