關於Java 鎖的知識整理與回顧(我的筆記):java
鎖有哪些,分別用來幹嗎?函數
Java實現鎖有兩種方式,synchronized關鍵字和Lock性能
(1)Lock(可判斷鎖狀態)優化
Lock是基於JDK層面實現。Lock的實現主要有ReentrantLock、ReadLock和WriteLock(引出鎖分類:)spa
①樂觀鎖/悲觀鎖:操作系統
樂觀鎖認爲讀多寫少,樂觀的認爲拿數據時,不會改數據,因此不會上鎖,而在更新數據時纔會判斷有無數據更新。悲觀鎖悲觀的認爲,寫多,拿數據時先設定數據被修改了,每次在讀寫數據時都會上鎖。線程
②公平鎖/非公平鎖:code
ReentrantLock在構造函數中提供是否公平鎖的初始化方式(默認是非公平鎖,就是說能夠變成公平鎖。即他和synchronized不一樣之處之一):對象
public ReentrantLock() { sync = new NonfairSync(); }
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
非公平鎖不按套路出牌,有可能形成「飢餓」現象,可是它的實際執行效率、吞吐量要高於公平鎖。blog
③獨享鎖/共享鎖
獨享鎖是指該鎖一次只能被一個線程所持有 (ReentrantLock、 Synchronized),共享鎖反之(ReadWriteLock)。
④互斥鎖/讀寫鎖(ReadWriteLock)
互斥鎖/讀寫鎖像是獨享鎖/共享鎖的具體的實現。(從字面意思就解釋很清楚了)
⑤可重入鎖
指同一個線程在外層方法獲取鎖的時候,在進入內層方法會自動獲取鎖(ReentrantLock和Synchronized)。可重入鎖可必定程度避免死鎖。
⑥自旋鎖
自旋鎖是指嘗試獲取鎖的線程不會阻塞,而是採用循環的方式嘗試獲取鎖。「採用循環的方式」說明要一直佔用CPU資源,浪費啊。在判斷持有鎖的線程會在很短的時間釋放鎖,用它就划算了,不用上下文來回切換了。
⑦偏向鎖/輕量級鎖/重量級鎖
這是jdk1.6中對Synchronized鎖作的優化,對象頭在不一樣鎖狀態下的標誌位存儲。
偏向鎖:加鎖/解鎖開銷少,適用於只有一個線程訪問同步塊場景;輕量級鎖:競爭線程不會堵塞,追求響應速度時用它;重量級鎖:線程競爭不使用自旋,不會消耗CPU,吞吐量大。(儘可能先考慮使用輕量級鎖)
(2)synchronized(不可判斷鎖狀態):
synchronized基於JVM層面實現。synchronized能夠把任意的非Null的對象看成瑣,它是非公平鎖(且沒法變成公平鎖)、獨享的可重入的悲觀鎖。使用synchronized比較省事兒,可是它是一個重量級操做,須要調用操做系統相關接口,性能較低,鎖開銷可能較大。
同時,synchronized它在不斷的被優化,在JDK1.5以後synchronized引入了偏向鎖,輕量級鎖和重量級鎖,java 6有適應自旋、鎖粗化、偏向鎖等,以後還設置一堆標記位,減小得到鎖和釋放鎖帶來的性能消耗,鎖開銷小了,效率高了。