2017-02-17 47 views
1

我正在尋找一種解決方案,允許多個線程讀取共享資源(允許併發),但隨後鎖定這些讀取線程,一旦線程進入變異塊,實現兩全其美。併發讀取但鎖定編輯

class Foo { 

    Map<String, String> sharedResource; 

    public void read() // multiple reading threads allowed, concurrency ok, lock this only if a thread enters the mutating block below. 
    { 
     // read concurrently unless a thread enters mutating blocks add/remove 
    } 

    public void add() // this should lock any threads entering this block as well as lock the reading threads above 
    { 
     synchronized(sharedResource) // lock remove and read 
     { 
     } 
    } 

    public void remove() // lock add and read 
    { 
     synchronized(sharedResource) 
     { 
     } 
    } 
} 

在Java中有這樣的解決方案嗎?

回答

4

這是一個典型的讀/寫鎖的情景:

class Foo { 

    Map<String, String> sharedResource; 
    ReadWriteLock lock = new ReentrantReadWriteLock(); 

    public void read() { 
     lock.readLock().lock(); 
     try { 
      // read 
     } finally { 
      lock.readLock().unlock(); 
     } 
    } 

    public void add() { 
     lock.writeLock().lock(); 
     try { 
      // add 
     } finally { 
      lock.writeLock().unlock(); 
     } 
    } 

    public void remove() { 
     lock.writeLock().lock(); 
     try { 
      // remove 
     } finally { 
      lock.writeLock().unlock(); 
     } 
    } 
} 

讀取鎖可以共享,但寫鎖是獨佔讀取和寫入。

+0

感謝這個例子,這似乎是我用C#中的ConcurrentDictionary工作的一個快速問題,你如何評價Java中的ConcurrentHashMap?是否與你給出的東西相當我作爲答案? – user2727195

+0

假設它實際上是一個我們正在討論的Map,那麼在某些Map實現中執行讀操作實際上並不會改變該映射:https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html 。您需要確保Map實施與您的鎖定策略一致。另外,還有Map實現可以在不需要外部鎖定的情況下有效地允許多個閱讀器:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html。 –

+0

@ user2727195 ConcurrentHashMap'通常是您的情況下推薦的解決方案。 – shmosel