您好,登錄后才能下訂單哦!
本篇內容介紹了“如何使用lock.lock()”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
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:為了保證當前線程執行過程中出現異常時,鎖依然能被釋放掉,避免死鎖的產生
我們來改動一下上面的代碼,看看會產生什么樣的影響
ReentrantLock lock = new ReentrantLock(); try { lock.lock(); // access the resource protected by this lock } finally { lock.unlock(); }
看著沒問題呀,為啥文章開始不建議這么用?先說下可能會存在的問題
異常堆棧丟失
假設在 lock.lock 方法中加鎖異常(千萬不要杠),那么會進入 finally 語句塊中進行解鎖
繼續跟進,看一下 lock.unlock() 源碼中是如何處理的
lock.lock() 拋出異常有可能還沒獲取到鎖,那么 解鎖源碼中將當前線程比較擁有鎖線程肯定是不相等的,所以會拋出 IMSE (IllegalMonitorStateException)異常
我重寫了 ReentrantLock 加鎖代碼的邏輯,在里面拋出了異常,一起看下會出現什么情況
final void lock() { // 模擬加鎖未成功就拋出異常 if (true) { throw new RuntimeException("報錯啦!!!"); } if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); }
根據下圖可以看出 加鎖時異常堆棧被 "吞掉了",悄無聲息的就沒了。當然這只是舉例,但是誰能保證加鎖未成功時不會拋出異常呢
真實存在的 BUG
上面代碼示例中都是在 try 的第一行寫 lock,出現問題的可能性極低。這里給大家提供一個反面教材,千萬千萬不要有這種類似行為
示例代碼中把 lock 放到了 try 語句塊里,然后 lock 加鎖前面還有可能會產生異常的代碼,這種就涼了,誰用誰涼的那種
“如何使用lock.lock()”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。