在讀不少併發文章中,會說起各類各樣鎖如公平鎖,樂觀鎖等等,這篇文章介紹各類鎖的分類。介紹的內容以下:算法
公平鎖是指多個線程按照申請鎖的順序來獲取鎖。 非公平鎖是指多個線程獲取鎖的順序並非按照申請鎖的順序,有可能後申請的線程比先申請的線程優先獲取鎖。有可能,會形成優先級反轉或者飢餓現象。 對於Java ReentrantLock而言,經過構造函數指定該鎖是不是公平鎖,默認是非公平鎖。非公平鎖的優勢在於吞吐量比公平鎖大。 對於Synchronized而言,也是一種非公平鎖。因爲其並不像ReentrantLock是經過AQS(AbstractQueuedSynchronizer)的來實現線程調度,因此並無任何辦法使其變成公平鎖。編程
可重入鎖又名遞歸鎖,是指在同一個線程在外層方法獲取鎖的時候,在進入內層方法會自動獲取鎖。說的有點抽象,下面會有一個代碼的示例。 對於Java ReentrantLock而言, 他的名字就能夠看出是一個可重入鎖,其名字是Re entrant Lock從新進入鎖。 對於Synchronized而言,也是一個可重入鎖。可重入鎖的一個好處是可必定程度避免死鎖。數組
synchronized void setA () throws Exception{
Thread.sleep(1000);
setB();
}
synchronized void setB () throws Exception{
Thread.sleep(1000);
}
複製代碼
上面的代碼就是一個可重入鎖的一個特色,若是不是可重入鎖的話,setB可能不會被當前線程執行,可能形成死鎖。bash
上面講的獨享鎖/共享鎖就是一種廣義的說法,互斥鎖/讀寫鎖就是具體的實現。多線程
樂觀鎖與悲觀鎖不是指具體的什麼類型的鎖,而是指看待併發同步的角度。併發
分段鎖實際上是一種鎖的設計,並非具體的一種鎖,對於ConcurrentHashMap而言,其併發的實現就是經過分段鎖的形式來實現高效的併發操做。函數
咱們以ConcurrentHashMap來講一下分段鎖的含義以及設計思想,ConcurrentHashMap中的分段鎖稱爲Segment,它即相似於HashMap(JDK7與JDK8中HashMap的實現)的結構,即內部擁有一個Entry數組,數組中的每一個元素又是一個鏈表;同時又是一個ReentrantLock(Segment繼承了ReentrantLock)。性能
當須要put元素的時候,並非對整個hashmap進行加鎖,而是先經過hashcode來知道他要放在那一個分段中,而後對這個分段進行加鎖,因此當多線程put的時候,只要不是放在一個分段中,就實現了真正的並行的插入。ui
可是,在統計size的時候,可就是獲取hashmap全局信息的時候,就須要獲取全部的分段鎖才能統計。spa
分段鎖的設計目的是細化鎖的粒度,當操做不須要更新整個數組的時候,就僅僅針對數組中的一項進行加鎖操做。
這三種鎖是指鎖的狀態,而且是針對Synchronized。在Java 5經過引入鎖升級的機制來實現高效Synchronized。這三種鎖的狀態是經過對象監視器在對象頭中的字段來代表的。
在Java中,自旋鎖是指嘗試獲取鎖的線程不會當即阻塞,而是採用循環的方式去嘗試獲取鎖,這樣的好處是減小線程上下文切換的消耗,缺點是循環會消耗CPU。 典型的自旋鎖實現的例子,能夠參考自旋鎖的實現