Java併發之顯式鎖和隱式鎖的區別
在面試的過程中有可能會問到:在Java併發程式設計中,鎖有兩種實現:使用隱式鎖和使用顯示鎖分別是什麼?兩者的區別是什麼?所謂的顯式鎖和隱式鎖的區別也就是說說Synchronized(下文簡稱:sync)和lock(下文就用ReentrantLock來代之lock)的區別。
本文主要內容:將通過七個方面詳細介紹sync和lock的區別。通過生活case中的X二代和普通人比較大家更容易理解這兩者之間的區別
Java中隱式鎖:synchronized;顯式鎖:lock
sync和lock的區別
一:出身不同
從sync和lock的出身(原始的構成)來看看兩者的不同。
Sync:Java中的關鍵字,是由JVM來維護的。是JVM層面的鎖。
Lock:是JDK5以後才出現的具體的類。使用lock是呼叫對應的API。是API層面的鎖
sync是底層是通過monitorenter進行加鎖(底層是通過monitor物件來完成的,其中的wait/notify等方法也是依賴於monitor物件的。只有在同步塊或者是同步方法中才可以呼叫wait/notify等方法的。因為只有在同步塊或者是同步方法中,JVM才會呼叫monitory物件的);通過monitorexit來退出鎖的。
而lock是通過呼叫對應的API方法來獲取鎖和釋放鎖的。
我們通過Javap命令來檢視呼叫sync和lock的彙編指令:
編輯
從編譯後的彙編指令,我們也能夠清晰的看出sync關鍵字和lock的區別。
第一不同一句話概述:可以把sync理解為官二代或者是星二代。從孃胎出來自帶光環的。Lock就是我們普通努力上進的人。
二:使用方式不同
Sync是隱式鎖。Lock是顯示鎖
所謂的顯示和隱式就是在使用的時候,使用者要不要手動寫程式碼去獲取鎖和釋放鎖的操作。
我們大家都知道,在使用sync關鍵字的時候,我們使用者根本不用寫其他的程式碼,然後程式就能夠獲取鎖和釋放鎖了。那是因為當sync程式碼塊執行完成之後,系統會自動的讓程式釋放佔用的鎖。Sync是由系統維護的,如果非邏輯問題的話話,是不會出現死鎖的。
在使用lock的時候,我們使用者需要手動的獲取和釋放鎖。如果沒有釋放鎖,就有可能導致出現死鎖的現象。手動獲取鎖方法:lock.lock()。釋放鎖:unlock方法。需要配合tyr/finaly語句塊來完成。
兩者用法對比如下:
編輯
用生活中的一個case來形容這個不同:官二代和普通人的你在進入機關大院的時候待遇。官二代不需要出示什麼證件就可以進入,但是你需要手動出示證件才可以進入。
三:等待是否可中斷
Sync是不可中斷的。除非丟擲異常或者正常執行完成
Lock可以中斷的。中斷方式:
1:呼叫設定超時方法tryLock(long timeout ,timeUnit unit)
2:呼叫lockInterruptibly()放到程式碼塊中,然後呼叫interrupt()方法可以中斷
生活中小case來理解這一區別:官二代一般不會做飯。都會去餐廳點餐等待著餐廳出餐。普通人的你既可以去餐廳等待,如果等待時間長的話,你就可以回去自己做飯了。
四:加鎖的時候是否可以公平
Sync;非公平鎖
lock:兩者都可以的。預設是非公平鎖。在其構造方法的時候可以傳入Boolean值。
true:公平鎖
false:非公平鎖
生活中小case來理解這個區別:官二代一般都不排隊,喜歡插隊的。普通人的你雖然也喜歡插隊。但是如果遇到讓排隊的情況下,你還是會排隊的。
Lock的公平鎖和非公平鎖:
五:鎖繫結多個條件來condition
Sync:沒有。要麼隨機喚醒一個執行緒;要麼是喚醒所有等待的執行緒。
Lock:用來實現分組喚醒需要喚醒的執行緒,可以精確的喚醒,而不是像sync那樣,不能精確喚醒執行緒。
六:從效能比較
生活小case理解:在我們一般的認知中,官二代一般都是比較坑爹的吧。但是這幾年也有很多官二代或者是富二代改變了態度,端正自己態度,靠自己能力而不是拼爹了。
七:從使用鎖的方式比較
歡迎來聊~