新聞中心
本文轉(zhuǎn)載自微信公眾號「源碼興趣圈」,作者龍臺。轉(zhuǎn)載本文請聯(lián)系源碼興趣圈公眾號。

創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),漢中企業(yè)網(wǎng)站建設(shè),漢中品牌網(wǎng)站建設(shè),網(wǎng)站定制,漢中網(wǎng)站建設(shè)報價,網(wǎng)絡營銷,網(wǎng)絡優(yōu)化,漢中網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。
前言
面試官:小伙子,JUC 并發(fā)包下的可重入鎖 ReentrantLock 在代碼里實際使用過么
混子:用過,ReentrantLock 是 JDK 提供的可重入的鎖。提供對 共享資源的獨占訪問,一次只能有一個線程可以獲取該鎖
面試官:你覺得,ReentrantLock#lock 方法寫到 try 語句外面還是里面
混子:我......
面試官:我們不合適,你走吧
先給出結(jié)論,lock.lock() 最規(guī)范的寫法是寫到 try 語句的外面
lock.lock()
Oracle 文檔中在介紹鎖的使用時有一段代碼,我們以 ReentrantLock 舉例,代碼如下所示:
- ReentrantLock lock = new ReentrantLock();
- lock.lock();
- try {
- // access the resource protected by this lock
- } finally {
- lock.unlock();
- }
Q:為什么要把 lock.unlock() 放到 finally 語句塊?
A:為了保證當前線程執(zhí)行過程中出現(xiàn)異常時,鎖依然能被釋放掉,避免死鎖的產(chǎn)生
我們來改動一下上面的代碼,看看會產(chǎn)生什么樣的影響
- ReentrantLock lock = new ReentrantLock();
- try {
- lock.lock();
- // access the resource protected by this lock
- } finally {
- lock.unlock();
- }
看著沒問題呀,為啥文章開始不建議這么用?先說下可能會存在的問題
異常堆棧丟失
假設(shè)在 lock.lock 方法中加鎖異常(千萬不要杠),那么會進入 finally 語句塊中進行解鎖
繼續(xù)跟進,看一下 lock.unlock() 源碼中是如何處理的
lock.lock() 拋出異常有可能還沒獲取到鎖,那么 解鎖源碼中將當前線程比較擁有鎖線程肯定是不相等的,所以會拋出 IMSE (IllegalMonitorStateException)異常
我重寫了 ReentrantLock 加鎖代碼的邏輯,在里面拋出了異常,一起看下會出現(xiàn)什么情況
- final void lock() {
- // 模擬加鎖未成功就拋出異常
- if (true) {
- throw new RuntimeException("報錯啦?。。?);
- }
- if (compareAndSetState(0, 1))
- setExclusiveOwnerThread(Thread.currentThread());
- else
- acquire(1);
- }
根據(jù)下圖可以看出 加鎖時異常堆棧被 "吞掉了",悄無聲息的就沒了。當然這只是舉例,但是誰能保證加鎖未成功時不會拋出異常呢
真實存在的 BUG
上面代碼示例中都是在 try 的第一行寫 lock,出現(xiàn)問題的可能性極低。這里給大家提供一個反面教材,千萬千萬不要有這種類似行為
示例代碼中把 lock 放到了 try 語句塊里,然后 lock 加鎖前面還有可能會產(chǎn)生異常的代碼,這種就涼了,誰用誰涼的那種
結(jié)尾
所以關(guān)于要不要把 lock.lock() 寫到 try 語句塊里,文章的結(jié)論是:
最好是把 lock.lock() 加鎖方法寫到 try 外面,這是一種規(guī)范,而不是強制
如果你非要寫到 try 里面,那么 請寫到 try 語句塊的第一行,或者 lock 加鎖方法前面不會存在可能出現(xiàn)異常的代碼
最后,如果你代碼中加鎖放到了 try 語句里,麻煩參考第 1 點
新聞名稱:獨家報道lock.lock()寫在try外面?
轉(zhuǎn)載來源:http://www.dlmjj.cn/article/dphopep.html


咨詢
建站咨詢
