JDK基礎--Java中的鎖概念

Java中的鎖概念

掌握Java中鎖是Java多線程編程中繞不開的知識,只有知道理解Java各類鎖才能在編碼過程當中靈活運用,寫出更高效的多線程程序。而理解掌握鎖的第一步,可從宏觀上對比理解一下各類鎖概念。java

在學習java的過程當中會遇到各個各樣鎖的概念:公平鎖/非公平鎖、可重入鎖、單獨鎖/共享鎖、互斥鎖/讀寫鎖、樂觀鎖/悲觀鎖、分段鎖、偏向鎖/輕量級鎖/重量級鎖、自旋鎖、閉鎖、活鎖,固然最高名的鎖就是無鎖,也是高併發過程當中的上層武功算法

在這些概念中,有的指鎖的狀態或類型, 有的指鎖的設計,在這裏整理並記錄一下:編程

1、公平鎖/非公平鎖數組

1.公平鎖是指按多個線程申請鎖的順序來獲取鎖。安全

2.非公平鎖是指多個線程獲取鎖的順序並非按照申請鎖的順序,有可能後申請的線程比先申請的線程優先獲取鎖。有可能,會形成優先級反轉或者飢餓現象。多線程

好比:對於Java ReentrantLock而言,經過構造函數指定該鎖是不是公平鎖,默認是非公平鎖。非公平鎖的優勢在於吞吐量比公平鎖大。併發

對於Synchronized而言,也是一種非公平鎖。因爲其並不像ReentrantLock是經過AQS(AbstractQueuedSynchronized 抽象的隊列式的同步器 ReentrantLock,Semaphore,CountDownLatch,ReentrantReadWriteLock,FutureTask)的來實現線程調度,因此並無任何辦法使其變成公平鎖。函數

2、可重入鎖高併發

可重入鎖又名遞歸鎖,是指在同一個線程在外層方法獲取鎖的時候,在進入內層方法會自動獲取鎖工具

ReentrantLock、Synchronized都是可重入鎖

synchronized void setA() throws Exception{
    Thread.sleep(1000);
    setB();
}

synchronized void setB() throws Exception{
    Thread.sleep(1000);
}

3、獨享鎖/共享鎖

1.獨享鎖是指該鎖一次只能被一個線程所持有。

2.共享鎖是指該鎖可被多個線程所持有。

對於ReentrantLock而言,其是獨享鎖。可是對於Lock的另外一個實現類ReadWriteLock,其讀鎖是共享鎖,其寫鎖是獨享鎖。

讀鎖的共享鎖可保證併發讀是很是高效的,讀寫,寫讀 ,寫寫的過程是互斥的。

獨享鎖與共享鎖也是經過AQS來實現的,經過實現不一樣的方法,來實現獨享或者共享。

對於Synchronized而言,固然是獨享鎖。

4、互斥鎖/讀寫鎖

上面講的獨享鎖/共享鎖就是一種廣義的說法,互斥鎖/讀寫鎖就是具體的實現。互斥鎖在Java中的具體實現就是ReentrantLock

讀寫鎖在Java中的具體實現就是ReadWriteLock

5、樂觀鎖/悲觀鎖

不是具體類型的鎖,而是指看待併發同步的角度

悲觀鎖在Java中的使用,就是利用各類鎖。

樂觀鎖在Java中的使用,是無鎖編程,經常採用的是CAS算法,典型的例子就是原子類,經過CAS自旋實現原子操做的更新。

6、分段鎖

分段鎖實際上是一種鎖的設計,並非具體的一種鎖,對於ConcurrentHashMap而言,其併發的實現就是經過分段鎖的形式來實現高效的併發操做,目的在於細化鎖粒度。

咱們以ConcurrentHashMap來講一下分段鎖的含義以及設計思想,ConcurrentHashMap中的分段鎖稱爲Segment,它即相似於HashMap(JDK7與JDK8中HashMap的實現)的結構,即內部擁有一個Entry數組,數組中的每一個元素又是一個鏈表;同時又是一個ReentrantLock(Segment繼承了ReentrantLock)。

7、偏向鎖、輕量級鎖、重量級鎖

這三種鎖是指鎖的狀態,而且是針對Synchronized。在Java 5經過引入鎖升級的機制來實現高效Synchronized。這三種鎖的狀態是經過對象監視器在對象頭中的字段來代表的。

偏向鎖是指一段同步代碼一直被一個線程所訪問,那麼該線程會自動獲取鎖。下降獲取鎖的代價。

輕量級鎖是指當鎖是偏向鎖的時候,被另外一個線程所訪問,偏向鎖就會升級爲輕量級鎖,其餘線程會經過自旋的形式嘗試獲取鎖,不會阻塞,提升性能。

重量級鎖是指當鎖爲輕量級鎖的時候,另外一個線程雖然是自旋,但自旋不會一直持續下去,當自旋必定次數的時候,尚未獲取到鎖,就會進入阻塞,該鎖膨脹爲重量級鎖。重量級鎖會讓其餘申請的線程進入阻塞,性能下降。

8、自旋鎖

在Java中,自旋鎖是指嘗試獲取鎖的線程不會當即阻塞,而是採用循環的方式去嘗試獲取鎖,這樣的好處是減小線程上下文切換的消耗,缺點是循環會消耗CPU。

9、閉鎖

閉鎖是一種同步工具類,能夠延遲線程的進度直到其到達終止狀態。閉鎖的做用至關於一扇門:在閉鎖到達結束狀態以前,這扇門一直是關閉的,而且沒有任何線程能經過,當到達結束狀態時,這扇門會打開容許全部的線程經過。當閉鎖到達結束狀態後,將不會再改變狀態,所以這扇門將永遠保持打開狀態。閉鎖能夠用來確保某些活動指導其餘活動都完成後才繼續執行。CountDownLatch就是一種靈活的閉鎖實現。

10、活鎖

LiveLock是一種形式活躍性問題,該問題儘管不會阻塞線程,但也不能繼續執行,由於線程將不斷重複執行相同的操做,並且總會失敗。活鎖一般發送在處理事務消息的應用程序中:若是不能成功地處理某個消息,那麼消息處理機制將回滾整個事務,並將它從新放到隊列的開頭:若是不能成功地處理某個消息,那麼消息處理機制將回滾整個事務,並將它從新放到隊列的開頭。若是消息處理器在處理某種特定類型的消息時存在錯誤並致使它失敗,那麼每當這個消息從隊列中取出並傳遞到存在錯誤的處理器時,都會發生事務回滾。因爲這條消息又被放回到隊列開頭,所以處理器將被反覆調用,並返回相同的結果。

11、無鎖

要保證現場安全,並非必定就要進行同步,二者沒有因果關係。同步只是保證共享數據爭用時的正確性的手段,若是一個方法原本就不涉及共享數據,那它天然就無須任何同步措施去保證正確性,所以會有一些代碼天生就是線程安全的。

無狀態編程。無狀態代碼有一些共同的特徵:不依賴於存儲在對上的數據和公用的系統資源、用到的狀態量都由參數中傳入、不調用非無狀態的方法等。能夠參考Servlet。

線程本地存儲。能夠參考ThreadLocal

volatile

CAS

協程:在單線程裏實現多任務的調度,並在單線程裏維持多個任務間的切換  

相關文章
相關標籤/搜索