成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

什么是可中斷鎖?有什么用?怎么實現?

開發 后端
在 Java 中有兩種鎖,一種是內置鎖 synchronized,一種是顯示鎖 Lock,所謂的中斷鎖指的是鎖在執行時可被中斷,也就是在執行時可以接收 interrupt 的通知,從而中斷鎖執行。

[[422997]]

作者 | 王磊

來源 | Java中文社群(ID:javacn666)

轉載請聯系授權(微信ID:GG_Stone

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

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

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

為什么需要可中斷鎖?

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

  1. import java.util.concurrent.locks.Lock; 
  2. import java.util.concurrent.locks.ReentrantLock; 
  3.  
  4. publicclass InterruptiblyExample { 
  5.     public static void main(String[] args) { 
  6.         Lock lock = new ReentrantLock(); 
  7.  
  8.         // 創建線程 1 
  9.         Thread t1 = new Thread(new Runnable() { 
  10.             @Override 
  11.             public void run() { 
  12.                 lock.lock(); 
  13.                 System.out.println("線程 1:獲取到鎖."); 
  14.                 // 線程 1 未釋放鎖 
  15.             } 
  16.         }); 
  17.         t1.start(); 
  18.  
  19.         // 創建線程 2 
  20.         Thread t2 = new Thread(new Runnable() { 
  21.             @Override 
  22.             public void run() { 
  23.                 // 先休眠 0.5s,讓線程 1 先執行 
  24.                 try { 
  25.                     Thread.sleep(500); 
  26.                 } catch (InterruptedException e) { 
  27.                     e.printStackTrace(); 
  28.                 } 
  29.                 // 獲取鎖 
  30.                 System.out.println("線程 2:等待獲取鎖."); 
  31.                 lock.lock(); 
  32.                 try { 
  33.                     System.out.println("線程 2:獲取鎖成功."); 
  34.                 } finally { 
  35.                     lock.unlock(); 
  36.                 } 
  37.             } 
  38.         }); 
  39.         t2.start(); 
  40.     } 

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

從上述結果可以看出,此時線程 2 在等待獲取鎖的操作,然而經歷了 N 久之后...再次查看結果,依然是熟悉的畫面:

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

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

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

使用中斷鎖

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

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

  1. import java.util.concurrent.locks.Lock; 
  2. import java.util.concurrent.locks.ReentrantLock; 
  3.  
  4. publicclass InterruptiblyExample { 
  5.     public static void main(String[] args) throws InterruptedException { 
  6.         Lock lock = new ReentrantLock(); 
  7.  
  8.         // 創建線程 1 
  9.         Thread t1 = new Thread(new Runnable() { 
  10.             @Override 
  11.             public void run() { 
  12.                 try { 
  13.                     // 加鎖操作 
  14.                     lock.lock(); 
  15.                     System.out.println("線程 1:獲取到鎖."); 
  16.                 } catch (InterruptedException e) { 
  17.                     e.printStackTrace(); 
  18.                 } 
  19.                 // 線程 1 未釋放鎖 
  20.             } 
  21.         }); 
  22.         t1.start(); 
  23.  
  24.         // 創建線程 2 
  25.         Thread t2 = new Thread(new Runnable() { 
  26.             @Override 
  27.             public void run() { 
  28.                 // 先休眠 0.5s,讓線程 1 先執行 
  29.                 try { 
  30.                     Thread.sleep(500); 
  31.                 } catch (InterruptedException e) { 
  32.                     e.printStackTrace(); 
  33.                 } 
  34.                 // 獲取鎖 
  35.                 try { 
  36.                     System.out.println("線程 2:嘗試獲取鎖."); 
  37.                     lock.lockInterruptibly(); // 可中斷鎖 
  38.                     System.out.println("線程 2:獲取鎖成功."); 
  39.                 } catch (InterruptedException e) { 
  40.                     System.out.println("線程 2:執行已被中斷."); 
  41.                 } 
  42.             } 
  43.         }); 
  44.         t2.start(); 
  45.  
  46.         // 等待 2s 后,終止線程 2 
  47.         Thread.sleep(2000); 
  48.         if (t2.isAlive()) { // 線程 2 還在執行 
  49.             System.out.println("執行線程的中斷."); 
  50.             t2.interrupt(); 
  51.         } else { 
  52.             System.out.println("線程 2:執行完成."); 
  53.         } 
  54.     } 

以上代碼執行結果如下:

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

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

  1. import java.util.concurrent.locks.Lock; 
  2. import java.util.concurrent.locks.ReentrantLock; 
  3.  
  4. publicclass InterruptiblyExample { 
  5.     public static void main(String[] args) throws InterruptedException { 
  6.         Lock lock = new ReentrantLock(); 
  7.  
  8.         // 創建線程 1 
  9.         Thread t1 = new Thread(new Runnable() { 
  10.             @Override 
  11.             public void run() { 
  12.                 try { 
  13.                     // 加鎖操作 
  14.                     lock.lockInterruptibly(); 
  15.                     System.out.println("線程 1:獲取到鎖."); 
  16.                 } catch (InterruptedException e) { 
  17.                     e.printStackTrace(); 
  18.                 } 
  19.                 // 線程 1 未釋放鎖 
  20.             } 
  21.         }); 
  22.         t1.start(); 
  23.  
  24.         // 創建線程 2 
  25.         Thread t2 = new Thread(new Runnable() { 
  26.             @Override 
  27.             public void run() { 
  28.                 // 先休眠 0.5s,讓線程 1 先執行 
  29.                 try { 
  30.                     Thread.sleep(500); 
  31.                 } catch (InterruptedException e) { 
  32.                     e.printStackTrace(); 
  33.                 } 
  34.                 // 獲取鎖 
  35.                 try { 
  36.                     System.out.println("線程 2:嘗試獲取鎖."); 
  37.                     lock.lock(); 
  38.                     System.out.println("線程 2:獲取鎖成功."); 
  39.                 } catch (Exception e) { 
  40.                     System.out.println("線程 2:執行已被中斷."); 
  41.                 } 
  42.             } 
  43.         }); 
  44.         t2.start(); 
  45.  
  46.         // 等待 2s 后,終止線程 2 
  47.         Thread.sleep(2000); 
  48.         if (t2.isAlive()) { // 線程 2 還在執行 
  49.             System.out.println("執行線程的中斷."); 
  50.             t2.interrupt(); 
  51.         } else { 
  52.             System.out.println("線程 2:執行完成."); 
  53.         } 
  54.     } 

以上程序執行結果如下:

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

總結

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

 

責任編輯:姜華 來源: Java中文社群
相關推薦

2022-02-16 22:37:00

流式SQLSQL數據庫

2024-01-25 10:23:22

對象存儲存儲數據

2021-02-18 07:55:27

數據湖存儲數據

2020-08-10 07:44:13

虛擬內存交換內存Linux

2009-06-17 15:51:55

java有什么用

2017-11-22 15:50:58

Netty微服務RPC

2022-05-05 07:38:32

volatilJava并發

2017-09-19 15:22:44

2024-03-04 07:37:40

MySQL記錄鎖

2022-05-30 07:34:33

三范式Java

2021-02-21 23:49:45

比特幣貨幣人民幣

2024-02-19 00:00:00

Python?starmap函數

2019-10-25 09:50:03

網絡爬蟲蜘蛛Wi-Fi

2024-10-18 10:00:00

云計算虛擬

2021-07-13 09:08:19

磁盤陣列系統

2023-09-19 16:37:47

網絡

2022-02-16 22:50:28

JVMJDKJRE

2020-10-20 09:57:04

量子計算人工智能技術

2022-12-05 13:58:36

2020-06-04 18:21:34

CPU緩存Intel
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久av | 中文字幕av一区 | 国产高清在线观看 | 久久久久国产精品一区二区 | 久久夜夜 | 国产视频精品免费 | 久久久久久国产 | 亚洲电影在线播放 | 欧美成人hd | 国产激情视频网站 | 午夜视频在线免费观看 | 91久久国产综合久久 | www.jizzjizz| 在线看片国产精品 | 日韩伦理电影免费在线观看 | 免费精品视频 | 亚洲国产情侣自拍 | 一区二区视频在线 | 91av在线视频观看 | 欧美婷婷 | 中文字字幕在线中文乱码范文 | 成人三级视频 | 精品成人免费一区二区在线播放 | 亚洲欧美激情国产综合久久久 | 国产我和子的乱视频网站 | 免费观看成人av | www.成人免费视频 | 国产福利在线 | 成人h动漫精品一区二区器材 | 欧美高清性xxxxhdvideosex | 春色av| 理伦毛片| 欧美成人一级 | 日本超碰| 国产av毛片 | 久久久久久久久久久91 | 99这里只有精品视频 | 久久国产精品亚洲 | 国产高清亚洲 | 久久一二 | 天天插天天搞 |