"Java Concurrency in Practice"本にはスレッドセーフであるとされている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()
通話中に別のスレッドによってに変更された場合を考えることができます。これにより、keySet()
を反復しながらConcurrentModificationException
がスローされる可能性があります。
つまり、MonitorVehicleTracker
は完全にスレッドセーフではありませんか?またはスレッドセーフは、オブジェクトの構築が完了した後にのみ表示され、MonitorVehicleTracker
インスタンシエーション中にlocations
が変更されないようにするための呼び出しコードがありますか?
右; 'locations'の' Map'実装はスレッドセーフではありませんが、 'MonitorVehicleTracker'はです。 – erickson
同じことが、スレッドインターリーブのためにクラス不変条件が構築中に壊れている場合にも当てはまりますか? –
@PavloViazovskyy私はそう言うだろう –