2017-03-20 36 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()通話過程中修改被另一個線程。這可能導致ConcurrentModificationException在迭代keySet()時拋出。

那麼這是否意味着MonitorVehicleTracker不是完全線程安全的?或線程安全只有在對象構造完成後纔出現,並且調用代碼負責確保在MonitorVehicleTracker實例化期間locations不會被修改?

回答

2

不,該類仍然是線程安全的。

如果對象未能初始化,那麼這並不意味着它的類停止線程安全。這是一個線程安全的類,它沒有初始化,因爲它的參數被其他線程錯誤地修改了,而這個線程違反了thread-saftey合同。

+0

正確; 'locations'的'Map'實現不是線程安全的,但是'MonitorVehicleTracker'是。 – erickson

+0

這是否也適用於類不變量由於線程交錯而在構造期間被破壞的情況? –

+0

@PavloViazovskyy我會這麼說 –