[Java concurrent][Collections]

同步容器類

  • 同步容器類包括Vector和Hashtable,兩者是早期JDK的一部分。以及一些在JDK1.2中添加的能夠由Collections.synchronizedXxx等工廠方法建立的。
  • 這些類實現線程安全的方式是,將它們的狀態封裝起來,並對每一個公有方法都進行同步(synchronized),使得每次只有一個線程能訪問容器的狀態。
  • 同步容器類在一些狀況下,可能須要額外的客戶端加鎖來保護複合操做
    eg:
    public static Object getLast(Vector list) {
      synchronized(list) {
        int lastIndex = list.size() - 1;
        return list.get(lastIndex);
      }
    }
    

    好比在迭代的時候,須要加鎖,那就會嚴重下降併發。這時候也能夠考慮經過「克隆」容器的方法。經過考慮容器的大小、操做的開銷等因素來抉擇。html

  • 在迭代過程當中,若是對容器進行修改就會拋出ConcurrentModificationException的異常(該異常即便是在單線程也能夠拋出,即當對象直接從容器中刪除而非使用Iterator.remove()時)。
    The iterators returned by the iterator method of the collections
    * returned by all of this class's "collection view methods" are
    * fail-fast: if the Hashtable is structurally modified at any time
    * after the iterator is created, in any way except through the iterator's own
    * remove method, the iterator will throw a
    * ConcurrentModificationException

Hashtable

  • An instance of Hashtable has two parameters that affect its performance: initial capacity and load factor.
    The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created. 由於在有衝突的時候須要順序查找。
    The load factor (default 0.75) is a measure of how full the hash table is allowed to get before its capacity is automatically increased. 
  • variables are private;
    public function are synchronized
  • 用synchronized來鎖住整張表來實現線程安全,即每次鎖住整張表讓線程獨佔。

synchronizedList 

  • static function of Collections
  • Returns a synchronized (thread-safe) list backed by the specified list.
  • In order to guarantee serial access, it is critical that all access to the backing list is accomplished through the returned list.
  • 實際上就是把原生collections封裝在一個SynchronizedCollection內部,這個類有一個
    final Object mutex;   // Object on which to synchronized
    其內部的方法都是相似
    public boolean contains(Object o) { synchronized(mutex) {return c.contains(o); }}

併發容器

  • 同步容器是經過將操做串行化來實現它們的線程安全性,於是嚴重下降了併發性。
  • Java5.0提供了多種容器來改進同步容器的性能。好比
    • 增長了ConcurrentHashMap來替代同步且基於散列的Map
    • CopyOnWriteArrayList用於在遍歷操做爲主要操做的狀況下代替同步的List。
    • 增長了對一些常見覆合操做的支持,如「若沒有則添加」、替換以及有條件刪除等。

java.util.concurrent

  • refer javadoc.
  • java.util.concurrent: Utility classes commonly useful in concurrent programming.

Memory Consistency Properties

  • 首先,你須要知道happens-before,能夠參考link
  • The methods of all classes in java.util.concurrent and its subpackages extend these guarantees to higher-level synchronized. In particular:
    • Actions in a thread prior to placing an object into any concurrent collection happen-before actions subsequent to the access or removal of that element from the collection in another thread.
    • Actions in a thread prior to the submission of a Runnable to an Executor happen-before its execution begins. Similarly for Callables submitted to an ExecutorService.
    • Actions taken by the asynchronous computation represented by a Future happen-before actions subsequent to the retrieval of the result via Future.get() in another thread.
    • Actions prior to "releasing" synchronizer methods such as Lock.unlockSemaphore.release, and CountDownLatch.countDown happen-before actions subsequent to a successful "acquiring" method such as Lock.lockSemaphore.acquire,Condition.await, and CountDownLatch.await on the same synchronizer object in another thread.
    • For each pair of threads that successfully exchange objects via an Exchanger, actions prior to the exchange() in each thread happen-before those subsequent to the corresponding exchange() in another thread.
    • Actions prior to calling CyclicBarrier.await and Phaser.awaitAdvance (as well as its variants) happen-before actions performed by the barrier action, and actions performed by the barrier action happen-before actions subsequent to a successful return from the corresponding await in other threads.

ConcurrentHashMap

  • Hashtable存在的問題是:在每一個方法上都加鎖而下降了併發。
    ConcurrentHashMap採用的solution就是使用更細粒度的加鎖機制來實現更大程度的共享,即分段鎖(Lock Striping)。具體的原理是:
    內部使用Segment來表示這些不一樣的部分,每一個段其實就是一個小的hashtable,它們有本身的鎖。只要修改操做發生在不一樣的段上,就能夠併發進行。【The table is internally partitioned to try to permit the indicated number of concurrent updates without contention.】
    有的方法須要跨段,好比size()和contains(),它們可能須要鎖住整張表,這就須要按順序鎖定全部表,操做完畢後,又按順序釋放全部段的鎖。
  • ConcurrentHashMap在線程安全地基礎上提供了更好的併發寫能力,可是下降了對讀一致性的要求。(感受像CAP)
  • 實現上,大量利用了volatile,final,CAS(Compare and Swap)等lock-free技術來減小鎖競爭對性能的影響。

Source Code

  • TBD...
相關文章
相關標籤/搜索