Java中的鎖ReentrantLock詳解
一、 ReentrantLock使用
1.1 簡單使用
public class LockTest {
// 新建鎖
Lock lock = new ReentrantLock();
public static void main(String[] args) {
// 測試
LockTest test = new LockTest();
test.te();
}
public void te(){
try {
// 獲取鎖
lock.lock();
System.out.println("獲取到鎖執(zhí)行代碼!");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 一定注意 在finally中釋放鎖
lock.unlock();
}
}
}1.2 tryLock
Lock比synchronized還是多一些功能的,比如可以設(shè)置規(guī)定時(shí)間內(nèi)獲取不到鎖就返回,不一直阻塞。
一個(gè)不合時(shí)宜的例子就是:
synchronize就是一個(gè)舔狗,一直舔 直到天荒地老
lock 的 tryLock 就像是一個(gè)渣男,輕輕嘗試一下,不合適抓緊下一個(gè)
public class LockTest02 {
// 新建鎖
Lock lock = new ReentrantLock();
public static void main(String[] args) {
// 測試
LockTest02 test = new LockTest02();
new Thread(()->test.te()).start();
// test::teTryLock lambda寫法
new Thread(test::teTryLock).start();
}
private void teTryLock() {
boolean res = false;
try {
// 嘗試獲取 5秒鐘獲取不到就結(jié)束
res = lock.tryLock(5,TimeUnit.SECONDS);
if (res) {
System.out.println("teTryLock獲取到鎖了,執(zhí)行獲取到鎖的代碼");
} else{
System.out.println("teTryLock沒有獲取到鎖 執(zhí)行沒有獲取到鎖的代碼");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 如果獲取到鎖了 再釋放
if (res) {
lock.unlock();
}
}
}
public void te(){
try {
// 獲取鎖
lock.lock();
System.out.println("te獲取到鎖執(zhí)行代碼!");
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 一定注意 在finally中釋放鎖
lock.unlock();
System.out.println("te釋放鎖!");
}
}
}輸出結(jié)果:
te獲取到鎖執(zhí)行代碼!
teTryLock沒有獲取到鎖 執(zhí)行沒有獲取到鎖的代碼
te釋放鎖!
1.3 lockInterruptibly
synchronized 如果開始等待是不能結(jié)束的
但是Lock使用lockInterruptibly 可以被中斷 在異常捕獲里捕獲異常 然后做一些后置處理
public class LockTest03 {
// 新建鎖
Lock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
// 測試
LockTest03 test = new LockTest03();
new Thread(test::te).start();
Thread thread = new Thread(test::teLockInterruptibly);
thread.start();
Thread.sleep(3000);
thread.interrupt();
}
private void teLockInterruptibly() {
boolean res = true;
try {
// 嘗試獲取 5秒鐘獲取不到就結(jié)束
lock.lockInterruptibly();
System.out.println("獲取到鎖··");
} catch (InterruptedException e) {
//沒有正常獲取鎖 被Interrupt了
res = false;
System.out.println("InterruptedException:被打斷了 做一些其他處理");
} finally {
// 如果沒被打斷 是正常獲取鎖的(理論上是,也可能有其他異常)
if(res) {
lock.unlock();
}
}
}
public void te(){
try {
// 獲取鎖
lock.lock();
System.out.println("te獲取到鎖執(zhí)行代碼!");
// te 方法睡死過去了
Thread.sleep(10000000);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 一定注意 在finally中釋放鎖
lock.unlock();
System.out.println("te釋放鎖!");
}
}
}1.4 公平鎖
synchronized是非公平鎖 后來的也可能會(huì)先獲取到鎖
Lock鎖默認(rèn)也是非公平鎖
非公平鎖是什么樣的?
用不要臉的小強(qiáng)來做比喻,假設(shè)有10個(gè)人在排隊(duì)買餅,小強(qiáng)這時(shí)候也來買餅了,不要臉的他直接跑第一個(gè)位置,這時(shí)候如果正有人在選餅,那他就灰溜溜的走了,如果上一個(gè)人剛好買完,下一個(gè)人還沒有開始選,那不要臉的小強(qiáng)就會(huì)趁著這個(gè)間隙直接跟老板選餅. 這樣對(duì)于后邊排隊(duì)的是不公平的 所以稱為不公平鎖
在ReentrantLock的實(shí)現(xiàn)中,不要臉的小強(qiáng)會(huì)嘗試好幾次,最后都失敗的話他才會(huì)去隊(duì)尾排隊(duì)
Lock可以實(shí)現(xiàn)公平鎖:公平鎖就是lock的時(shí)候會(huì)先去排隊(duì)隊(duì)列里邊看看,有沒有人在排隊(duì),有的話站后邊去,可以看我寫過的AQS ,用公平鎖做的舉例 講到了源碼層
注意:公平鎖不是完全公平,公平鎖只是會(huì)檢查隊(duì)列里有沒有人排隊(duì),如果沒有自己去申請(qǐng)鎖,如果有自己去排隊(duì),去檢查有沒有人排隊(duì)的時(shí)候可能會(huì)出現(xiàn)不公平(地鐵一個(gè)人一大步竄你前邊了),進(jìn)隊(duì)列的時(shí)候也可能會(huì)出現(xiàn)不公平(地鐵一個(gè)人一大步竄你前邊了)
Lock lock = new ReentrantLock(true); // true表示公平
到此這篇關(guān)于Java中的鎖ReentrantLock詳解的文章就介紹到這了,更多相關(guān)ReentrantLock詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot集成ELK實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ)和日志管理的代碼示例
本文介紹在SpringBoot 2.7.18中集成Elasticsearch、Logstash、Kibana的步驟,簡單展示了ES增刪改查的API用法,測試Logstash日志收集,并實(shí)現(xiàn)Kibana數(shù)據(jù)看板可視化分析日志,需要的朋友可以參考下2025-09-09
IntelliJ IDEA安裝scala插件并創(chuàng)建scala工程的步驟詳細(xì)教程
這篇文章主要介紹了IntelliJ IDEA安裝scala插件并創(chuàng)建scala工程的步驟,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
Java System類詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
System類是jdk提供的一個(gè)工具類,有final修飾,不可繼承,由名字可以看出來,其中的操作多數(shù)和系統(tǒng)相關(guān)。這篇文章主要介紹了Java System類詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理,需要的朋友可以參考下2017-04-04
IDEA 中 maven 的 Lifecycle 和Plugins&n
IDEA 主界面右側(cè) Maven 標(biāo)簽欄有同樣的命令,比如 install,既在 Plugins 中存在,也在 Lifecycle中存在,到底選哪個(gè)?二者又有什么區(qū)別呢?下面小編給大家介紹下IDEA 中 maven 的 Lifecycle 和Plugins 的區(qū)別,感興趣的朋友一起看看吧2023-03-03
java中sleep方法和wait方法的五個(gè)區(qū)別
這篇文章主要介紹了java中sleep方法和wait方法的五個(gè)區(qū)別,sleep?方法和?wait?方法都是用來將線程進(jìn)入休眠狀態(tài),但是又有一些區(qū)別,下面我們就一起來看看吧2022-05-05

