Java中的鎖可以分為隐式鎖和顯示鎖,Lock接口的鎖都是顯示鎖。JVM内置鎖就是隐式鎖,synchronized就是隐式的鎖。
顯示鎖:需要手動釋放鎖,可以設定是否為公平鎖
隐式鎖:不需要手動釋放鎖,非公平鎖
Monitor
Lock接口實作的鎖底層是通過AQS同步隊列實作的。用到了unsafe.park()方法。synchronized 底層有一個monitor螢幕,會監控持有鎖的對象。如下圖:

monitorenter表示目前程式将進入同步塊 monitorexit表示即将退出同步塊,并且釋放鎖
那麼JVM怎麼知道我目前的對象是否已經加鎖了呢。
synchronized (object) {
//代碼邏輯
}
如上圖,Monitor調用Enter方法進入監視區,它會監視object對象裡面是否有鎖标記,如果沒有就給object加上鎖标記,并執行後面的邏輯,最後釋放鎖,取消object的鎖标記。Monitor.Exit退出監視區,并釋放鎖。
鎖Monitor.Enter進入後,發現對象object上面已經有鎖标記了,那麼傳回Monitor.Enter失敗,并退出Monitor。之後再循環重試。
對象頭
鎖标記儲存在對象頭(方法區的類資訊)中的Mark Word中。
鎖更新
由于JDK的優化,synchronized鎖有一個更新,極大的提升了鎖的性能。
鎖對象剛建立時,對象頭裡面是無鎖的狀态,當第一個線程進來時。鎖更新為偏向鎖;當第二個線程進來,更新為輕量級鎖;第三個線程進來,等待搶鎖,第四個,第五個線程進來也是等待争搶鎖。争搶的線程變多了,鎖就會更新為重量級鎖。
無鎖
無鎖态時 Mark Word 标記位為01,是否偏向标記為0。
偏向鎖
此時是否偏向标記為1。
輕量級鎖
鎖标志位
重量級鎖
更新為重量級鎖時,線程會有從使用者态到核心态的切換,是以說,大量線程搶鎖時,性能不是很好,建議使用Lock接口實作的鎖。
注意,以上兩種鎖都是單機的鎖,現在的系統都是分布式的,需要分布式鎖。可以用zookeeper或redis實作。市面上已經有成熟的分布式鎖架構。像Redisson,Curator等都很不錯。
Lock 與synchronized
(1)synchronized不會導緻死鎖現象發生;而Lock可能造成死鎖現象Lock可以讓等待。
(2)鎖的線程響應中斷,而synchronized卻不行。
(3)通過Lock可以知道有沒有成功擷取鎖,而synchronized卻無法辦到 。
(4)Lock可以提高多個線程進行讀操作的效率 。
(5)性能上,競争不激烈兩者差不多;非常激烈時(即有大量線程同時競争) Lock遠遠優于synchronized。是以說,在具體使用時要根據适當情況選擇。