#java #multithreading
#java #многопоточность
Вопрос:
Проходя параллелизм Java на практике, я наткнулся на приведенный ниже код.
Несмотря Mutablepoint
на то, что он не MonitorVehicleTracker
является потокобезопасным, он потокобезопасен, поскольку все инварианты, которые защищают карту местоположений, используют глубокое копирование. Я сомневаюсь, что все еще возможно изменить местоположение конкретного транспортного средства из изменяемой точки другим потоком, поскольку координаты x и y являются общедоступными, не создаст ли это каких-либо сопутствующих проблем? тогда как мы можем сказать, что 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);
}
}
@NonThreadSafe
public class MutablePoint {
public int x, y;
public MutablePoint() {
x = 0;
y = 0;
}
public MutablePoint(MutablePoint p) {
this.x = p.x;
this.y = p.y;
}
}
Ответ №1:
Несмотря MutablePoint
на то, что содержит общедоступные переменные, все экземпляры MutablePoint
s, возвращаемые, MotorVehicleTracker
являются копиями экземпляров в map . Из-за этого, если вызывающий получает экземпляр MutablePoint
и изменяет x
и y
, они отличаются от экземпляров, хранящихся в map in MotorVehicleTracker
. Так MotorVehicleTracker
и потокобезопасно. MutablePoint
нет, и его можно использовать для создания условий гонки. Эти условия гонки не будут задействованы MotorVehicleTracker
, потому что этот класс хранит только копии и возвращает копии.
Комментарии:
1. Единственная проблема с изменяемой точкой, которую я предполагаю, заключается в том, что какой-то поток может увидеть частично созданный экземпляр MutablePoint. Есть ли здесь какие-либо другие проблемы с параллелизмом, которые могут возникнуть?