03.21 “全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

難度

初級

學習時間

30分鐘

適合人群

零基礎

開發語言

Java

開發環境

  • JDK v11
  • IntelliJIDEA v2018.3

友情提示

  • 本教學屬於系列教學,內容具有連貫性,本章使用到的內容之前教學中都有詳細講解。
  • 本章內容針對零基礎或基礎較差的同學比較友好,可能對於有基礎的同學來說很簡單,希望大家可以根據自己的實際情況選擇繼續看完或等待看下一篇文章。謝謝大家的諒解!

1.溫故知新

前面在 一章中介紹了讀寫鎖ReadWriteLock

在 一章中介紹了讀鎖與寫鎖之間相互嵌套情況

在 一章中介紹了可重入讀寫鎖ReentrantReadWriteLock的獲取線程與讀寫鎖保持數系列方法

在 一章中介紹了可重入讀寫鎖ReentrantReadWriteLock的查詢是否有線程正在等待獲取讀寫鎖hasQueuedThreads()方法、獲取有多少個正在等待獲取讀寫鎖的線程getQueueLength()方法和查詢指定線程是否正在等待獲取讀寫鎖的hasQueuedThread(Thread thread)方法。

在 一章中介紹了可重入讀寫鎖ReentrantReadWriteLock與Condition的關係,在讀寫鎖中,寫鎖是支持Condition的,讀鎖是不支持Condition的,原因在於寫鎖在某一時刻最多隻能被一個線程擁有,而讀鎖在某一時刻最多可以被多個線程擁有,對於讀鎖而言,其他線程沒有必要等待獲取讀鎖,等待喚醒是毫無意義的。

在 一章中介紹了如何查詢Condition上是否有線程正在等待和有多少線程正在等待。用鎖的hasWaiters​(Condition condition)方法查詢Condition上是否有線程正在等待,再用getWaitQueueLength​(Condition condition)方法獲取Condition上等待的線程的個數。

現在介紹如何判斷任意線程是否已持有寫鎖。

2.判斷任意線程是否持有寫鎖isWriteLocked()方法

我們可以使用isWriteLocked()方法來判斷任意線程是否持有寫鎖。

請問這個方法有什麼用呢?

isWriteLocked()方法可以讓我們隨時查詢寫鎖是否已經被其他線程持有了,根據查詢結果我們就可以做出相應的操作。比如,寫鎖已經被其他線程持有了,我們現在是等還是結束線程。

既然isWriteLocked()方法是判斷當前線程是否獲取到寫鎖,那麼我們的isWriteLocked()方法就只跟ReentrantReadWriteLock可重入讀寫鎖有關了,跟ReentrantLock可重入鎖無關。

下面我們就來看看isWriteLocked()方法。

isWriteLocked()方法在ReentrantReadWriteLock類中的源碼:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

判斷任意線程是否持有寫鎖,當任意線程持有寫鎖時,方法返回true,否則返回false。

去掉註釋版:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

isWriteLocked()方法作用是判斷任意線程是否持有寫鎖,當任意線程持有寫鎖時,方法返回true,否則返回false。

訪問權限

public:isWriteLocked()方法是公開的。

boolean:isWriteLocked()方法返回boolean類型的值,當任意線程持有寫鎖時返回true,否則返回false。

isWriteLocked()方法只能被對象調用。

參數

無。

拋出的異常

無。

應用

下面我們就來試試isWriteLocked()方法。

首先,創建出讀寫鎖對象:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

其次,創建出讀鎖與寫鎖:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

然後,讓主線程去獲取寫鎖:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

最後,在獲取寫鎖內外各調用isWriteLocked()方法並輸出結果:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

例子書寫完畢。

運行程序,執行結果:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

從運行結果來看,符合預期。主線程在沒有獲取到寫鎖之前isWriteLocked()方法返回false,在獲取到寫鎖之後isWriteLocked()方法返回true。

3.任意線程與當前線程

上一小節說過,isWriteLocked()方法返回的是當任意線程持有寫鎖時返回true,否則返回false。

任意線程與當前線程在例子中指的是?

還是把例子改寫之後再說吧,有對比之後比較容易說清楚。

上一小節中只有主線程一個線程在競爭寫鎖,我們這時新建一個線程出來,並重寫run()方法:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

讓新建的線程去競爭寫鎖:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

並且在獲取到寫鎖之後睡3秒鐘:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

然後,啟動線程:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

最後,在啟動線程之後,使主線程睡1秒鐘,再獲取寫鎖:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

例子改寫完畢。

運行程序,執行結果:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

從運行結果來看,符合預期。

任意線程指的是?

例子中,任意線程指的是無論是主線程還是新創建出來的thread線程,誰獲取了寫鎖,isWriteLocked()方法都會返回true。

當前線程呢?

當前線程指的是執行isWriteLocked()方法的線程。

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

比如,在thread線程裡面執行的Thread.sleep()方法,那麼當前線程指的就是thread線程;

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

在主線程裡面執行的Thread.sleep()方法,那麼當前線程指的就是主線程。

當然了,我們ReentrantReadWriteLock類裡面還有一個判斷當前線程釋放持有寫鎖的方法,叫isWriteLockedByCurrentThread()。

4.isWriteLocked()方法與isWriteLockedByCurrentThread()方法對比

下面,修改上一小節例子。

在主線程獲取寫鎖的前後各調用一次isWriteLockedByCurrentThread()方法:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

並且在釋放鎖之後再調用一次:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

例子修改完畢,通過運行結果來對比isWriteLocked()方法與isWriteLockedByCurrentThread()方法的區別。

運行程序,執行結果:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

靜圖:

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

從運行結果來看,符合預期。

為什麼符合預期?

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

我們可以很明顯地從運行結果中看到,當其他線程已經持有寫鎖的情況下,isWriteLocked()方法返回的是true,isWriteLockedByCurrentThread()方法返回的是false。

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

在主線程獲取到寫鎖時,isWriteLocked()方法和isWriteLockedByCurrentThread()方法都返回的是true。

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有

在沒有線程獲取寫鎖時(即所有線程都釋放了寫鎖),isWriteLocked()方法和isWriteLockedByCurrentThread()方法都返回的是false。

這樣一來,isWriteLocked()方法和isWriteLockedByCurrentThread()方法的區別顯而易見了:

isWriteLocked()方法用於判斷當任意線程持有寫鎖時,方法返回true,否則返回false。

isWriteLockedByCurrentThread()方法用於判斷噹噹前線程持有寫鎖時,方法返回true,否則返回false。

請大家一定一定要注意!!!

最後,希望大家可以把這個例子照著寫一遍,然後再自己默寫一遍,方便以後碰到類似的面試題可以輕鬆應對。

祝大家編碼愉快!

GitHub

本章程序GitHub地址:https://github.com/gorhaf/Java2019/tree/master/Thread/ReadWriteLock/ReentrantReadWriteLock

總結

  • isWriteLocked()方法用於判斷當任意線程持有寫鎖時,方法返回true,否則返回false。
  • isWriteLockedByCurrentThread()方法用於判斷噹噹前線程持有寫鎖時,方法返回true,否則返回false。

至此,Java中判斷任意線程是否已持有寫鎖相關內容講解先告一段落,更多內容請持續關注。

答疑

如果大家有問題或想了解更多前沿技術,請在下方留言或評論,我會為大家解答。

上一章

下一章

學習小組

加入同步學習小組,共同交流與進步。

  • 方式一:關注頭條號Gorhaf,私信“Java學習小組”。
  • 方式二:關注公眾號Gorhaf,回覆“Java學習小組”。

全棧工程師學習計劃

關注我們,加入“全棧工程師學習計劃”。

“全棧2019”Java多線程第四十六章:判斷寫鎖已被任意線程持有


分享到:


相關文章: