天天看點

什麼是可中斷鎖?有什麼用?怎麼實作?

在 Java 中有兩種鎖,一種是内置鎖 synchronized,一種是顯示鎖 Lock,其中 Lock 鎖是可中斷鎖,而 synchronized 則為不可中斷鎖。

所謂的中斷鎖指的是鎖在執行時可被中斷,也就是在執行時可以接收 interrupt 的通知,進而中斷鎖執行。

PS:預設情況下 Lock 也是不可中斷鎖,但是可以通過特殊的“手段”,可以讓其變為可中斷鎖,接下來我們一起來看。

不可中斷鎖的問題是,當出現“異常”時,隻能一直阻塞等待,别無其他辦法,比如下面這個程式。下面的這個程式中有兩個線程,其中線程 1 先擷取到鎖資源執行相應代碼,而線程 2 在 0.5s 之後開始嘗試擷取鎖資源,但線程 1 執行時忘記釋放鎖了,這就造成線程 2 一直阻塞等待的情況,實作代碼如下:

以上代碼執行的結果如下:

從上述結果可以看出,此時線程 2 在等待擷取鎖的操作,然而經曆了 N 久之後...

再次檢視結果,依然是熟悉的畫面:

線程 2 還在阻塞等待擷取線程 1 釋放鎖資源,此時的線程 2 除了等之外,并無其他方法。

并且,但我們熟練的拿出了 JConsole,試圖得到一個死鎖的具體資訊時,卻得到了這樣的結果:

并沒有檢測到任何死鎖資訊,從上圖我們可以看出,當隻有一個鎖資源的時候,系統并不會把這種情況判定為死鎖,當然也沒有阻塞等待的具體資訊喽,此時隻剩下線程 2 孤單地等待着它的“鎖兒”。

然而,中斷鎖的出現,就可以打破這一僵局,它可以在等待一定時間之後,主動的中斷線程 2,以解決線程阻塞等待的問題。

中斷鎖的核心實作代碼是 lock.lockInterruptibly() 方法,它和 lock.lock() 方法作用類似,隻不過使用 lockInterruptibly 方法可以優先接收中斷的請求,中斷鎖的具體實作如下:

以上代碼執行結果如下:

從上述結果可以看出,當我們使用了 lockInterruptibly 方法就可以在一段時間之後,判斷它是否還在阻塞等待,如果結果為真,就可以直接将他中斷,如上圖效果所示。

但當我們嘗試将 lockInterruptibly 方法換成 lock 方法之後(其他代碼都不變),執行的結果就完全不一樣了,實作代碼如下:

以上程式執行結果如下:

從上圖可以看出,當使用 lock 方法時,即使調用了 interrupt 方法依然不能将線程 2 進行中斷。

本文介紹了中斷鎖的實作,通過顯示鎖 Lock 的 lockInterruptibly 方法來完成,它和 lock 方法作用類似,但 lockInterruptibly 可以優先接收到中斷的通知,而 lock 方法隻能“死等”鎖資源的釋放,同時這兩個方法的差別也是常見的面試題,希望本文對你有用。

線程的 4 種建立方法和使用詳解!

Java中使用者線程和守護線程差別這麼大?

深入了解線程池 ThreadPool

線程池的7種建立方式,強烈推薦你用它...

池化技術到達有多牛?看了線程和線程池的對比吓我一跳!

并發中的線程同步與鎖

synchronized 加鎖 this 和 class 的差別!

volatile 和 synchronized 的差別

輕量級鎖一定比重量級鎖快嗎?

這樣終止線程,竟然會導緻服務當機?

SimpleDateFormat線程不安全的5種解決方案!

ThreadLocal不好用?那是你沒用對!

ThreadLocal記憶體溢出代碼示範和原因分析!

Semaphore自白:限流器用我就對了!

CountDownLatch:别浪,等人齊再團!

CyclicBarrier:人齊了,司機就可以發車了!

synchronized 優化手段之鎖膨脹機制!

synchronized 中的 4 個優化,你知道幾個?

ReentrantLock 中的 4 個坑!

圖解:為什麼非公平鎖的性能更高?

死鎖的 4 種排查工具!

死鎖終結者:順序鎖和輪詢鎖!

輪詢鎖在使用時遇到的問題與解決方案!

關注公号「Java中文社群」檢視更多有意思、漲知識的 Java 并發文章。

關注下面二維碼,訂閱更多精彩内容。

什麼是可中斷鎖?有什麼用?怎麼實作?
什麼是可中斷鎖?有什麼用?怎麼實作?
什麼是可中斷鎖?有什麼用?怎麼實作?

關注公衆号(加好友):

什麼是可中斷鎖?有什麼用?怎麼實作?

作者:

王磊的部落格

出處:

http://vipstone.cnblogs.com/