面試官:你說說ReentrantLock和Synchronized區別!

大家好!又和大家見面了。爲了避免面試尷尬,今天同比較通俗語言和大家聊下ReentrantLock和Synchronized區別!另外:整理了一份Java面試寶典完整版PDF,已成文檔

使用方式

Synchronized可以修飾實例方法,靜態方法,代碼塊。自動釋放鎖。

ReentrantLock一般需要try catch finally語句,在try中獲取鎖,在finally釋放鎖。需要手動釋放鎖。

實現方式

Synchronized是重量級鎖。重量級鎖需要將線程從內核態和用戶態來回切換。如:A線程切換到B線程,A線程需要保存當前現場,B線程切換也需要保存現場。這樣做的缺點是耗費系統資源

ReentrantLock是輕量級鎖。採用cas+volatile管理線程,不需要線程切換切換,獲取鎖線程覺得自己肯定能成功,這是一種樂觀的思想(可能失敗)。

用一個形象例子來說明:比如您在看我這篇文章時,覺得“重量級鎖”概念不是很明白,就立刻去翻看關於“重量級鎖”的其他文章,過會兒回頭再繼續往下面看, 這種行爲我們稱爲切換。保存現場的意思就是你大腦需要記住你跳躍的點然後繼續閱讀,如果文章篇幅大,你的大腦可能需要記憶越多的東西,會越耗費腦神經。同理,在輕量級鎖中,你覺得“重量級鎖”概念不是很明白,他不會立刻去翻看其他文章,他會堅持會兒繼續看,如果實在不明白再去翻資料了。需要注意的是:這是兩種不一樣的思維方式,前者是被動阻塞悲觀鎖,狀態是block,後者是主動的阻塞樂觀鎖,狀態是wait。

公平和非公平

Synchronized只有非公平鎖。

ReentrantLock提供公平和非公平兩種鎖,默認是非公平的。公平鎖通過構造函數傳遞true表示。

用一個形象例子來說明:排隊打飯,Synchronized允許插隊,如果ReentrantLock是公平鎖,就不許插隊了。

可重入鎖

Synchronized和ReentrantLock都是可重入的,Synchronized是本地方法是C++實現,而ReentrantLock是JUC包用Java實現。

用一個形象例子來說明:如下圖:一個房中房,房裏外各有一把鎖,但只有唯一的鑰匙可以開,擁有鑰匙的人可以先進入門1,再進入門2,其中進入門2就是叫鎖可重入了。

在ReentrantLock中,重入次數用整形state表示。進入1次遞增1次,出來1次遞減1次。

可中斷的

Synchronized是不可中斷的。

ReentrantLock提供可中斷和不可中斷兩種方式。其中lockInterruptibly方法表示可中斷,lock方法表示不可中斷。

用一個形象例子來說明:叫練和叫練女朋友一起去做核酸,叫練女朋友排在前面,所以叫練女朋友進門先做,叫練在門外排隊等待過程中突然接到領導電話要回去修改bug,叫練現在有兩種選擇,1.不和女朋友打招呼,立即回去修改bug,2.等待女朋友做完核酸,進去和女朋友打個招呼,然後回去修改bug。這兩種情況最終都會導致一個結果,叫練無法完成核酸,在這兩種情況中,雖然叫練都被領導中斷了,但第一種情況叫練立即反饋領導叫可中斷,第二種情況是叫練爲了不做單身狗,打個招呼再去修改bug,需要注意的是“打招呼”需要提前獲取鎖,也就是需要等待叫練女朋友做完核酸檢測。如果是你,遇到叫練這種情況,你會怎麼辦?期待你的答覆!

條件隊列

Synchronized只有一個等待隊列。

ReentrantLock中一把鎖可以對應多個條件隊列。通過newCondition表示。

用一個形象例子來說明:母雞下蛋和撿蛋人對應生產者和消費者,母雞產蛋後,撿蛋人需要被母雞通知,母雞產蛋過程中,其中撿蛋人就會入條件隊列(等待隊列)。撿蛋人撿蛋完成後,撿蛋人需要通知母雞繼續產蛋,撿蛋人撿蛋過程中,母雞也需要加入條件隊列等待。

注意:有幾個概念需要說明下。同步隊列,條件隊列和等待隊列。

同步隊列:多線程同時競爭一把鎖失敗被掛起的線程。

條件隊列:正在執行的線程調用await/wait,從同步隊列加入的線程會進入條件隊列。正在執行線程調用signal/signalAll/notify/notifyAll,會將條件隊列一個線程或多個線程加入到同步隊列。

等待隊列:和條件隊列一個概念。

作者:叫練
原文鏈接:https://www.cnblogs.com/jiaolian/p/14329299.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章