2017-03-20 1 views
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() 통화 중에 다른 thread에 의해을 수정할 때 경우를 고려 할 수 있습니다. 이로 인해 keySet()을 반복하는 동안 ConcurrentModificationException이 던져 질 수 있습니다.

따라서 MonitorVehicleTracker은 스레드로부터 안전하지 않습니다. 또는 thread-safety은 객체 생성이 완료된 후에 만 ​​나타나며 MonitorVehicleTracker 인스턴스 생성 중에 locations이 수정되지 않도록 호출 코드가 책임 져야합니까?

답변

2

아니요, 클래스는 여전히 스레드로부터 안전합니다.

개체가 초기화되지 않으면 클래스의 스레드로부터의 안전이 중지되지 않는다는 의미는 아닙니다. 인수가 다른 스레드가 thread-saftey 계약을 위반하여 잘못 수정 되었기 때문에 초기화에 실패한 스레드 안전 클래스입니다.

+0

오른쪽; 'locations'의'Map' 구현체는 쓰레드 - 안전하지 않지만'MonitorVehicleTracker'는 있습니다. – erickson

+0

스레드 인터리빙으로 인해 클래스 invariant가 생성 도중 깨지는 경우에도 마찬가지입니까? –

+0

@PavloViazovskyy 나는 그렇게 말할 것이다. –