Безопасность потоков с использованием делегирования

#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. Есть ли здесь какие-либо другие проблемы с параллелизмом, которые могут возникнуть?