2016-11-04 28 views
1

我是Java新手和併發的東西。從Hashmap中同時添加或刪除元素並實現同步

該任務的目的是學習併發性。 - 所以當回答這個問題時,請記住,我應該只使用Hashmap(本質上不同步)並自己同步它。如果你提供更多的知識,但不是必需的。

我宣佈這樣一個HashMap:

private HashMap<String, Flight> flights = new HashMap<>(); 

的recordId是要刪除的飛行的關鍵。

Flight flightObj = flights.get(recordID); 

synchronized(flightObj){ 
        Flight deletedFlight = flights.remove(recordID); 
        editResponse = "Flight with flight ID " + deletedFlight.getFlightID() +" deleted successfully"; 
        return editResponse; 
       } 

現在我懷疑:在flightObj的基礎上同步很好嗎?


疑點二:

Flight newFlight = new Flight(FlightServerImpl.createFlightID()); 
flights.put(newFlight.getFlightID(),newFlight); 

如果我用上面的代碼創建flightts如果多個線程試圖執行該代碼會不會有任何數據一致性問題?爲什麼或者爲什麼不?

在此先感謝。

回答

1

迅速回答您的問題:

兩者都是不行的 - 你不能並行取出兩個不同的對象,你不能並行添加兩個不同的對象。

java documentation

如果多個線程訪問哈希映射同時,與線程中的至少一個在結構上修改了該映射,則必須將外部同步。 (結構修改是指添加或刪除一個或多個映射的任何操作;僅更改與實例已包含的鍵相關聯的值不是結構修改。)這通常通過同步某個自然封裝映射的對象來實現。如果不存在這樣的對象,則應使用Collections.synchronizedMap方法「映射」該映射。這是在創建時,這樣做可以防止意外的不同步訪問地圖:

因此,它的好了許多線程使用get同時,甚至put替換的對象。

但是,如果你刪除或添加一個新的對象 - 你需要在調用任何hashmap函數之前進行同步。

在這種情況下,您可以執行文檔中的建議並使用全局鎖定。但是,由於仍然允許一些有限的併發,所以您可以通過使用read/write lock來獲得併發性。

+0

謝謝你這麼多@Alex L.這樣一個簡單而全面的解答。我無法告訴你我現在的感受如何。 – Aakash

0

你可以做以下

class MySynchronizedHashMap<E> implements Collection<E>, Serializable { 
    private static final long serialVersionUID = 3053995032091335093L; 

    final Collection<E> c; // Backing Collection 
    final Object mutex;  // Object on which to synchronize 

    SynchronizedCollection(Collection<E> c) { 
     this.c = Objects.requireNonNull(c); 
     mutex = this; 
    } 

    public boolean add(E e) { 
     synchronized (mutex) {return c.add(e);} 
    } 
    public boolean remove(Object o) { 
     synchronized (mutex) {return c.remove(o);} 
    } 
} 

MySynchronizedHashMap mshm = new MySynchronizedHashMap<>(new HashMap<String, Flight>()); 
mshm.add(new Flight()); 
+0

你爲什麼要這樣做,而Java本身已經有這個設施(可能比這更好)?例如'集合。synchronizedMap','ConcurrentHashMap'等。 –

相關問題