1. 設置超時時間
使用JUC包中的Lock接口提供的tryLock方法.
該方法在獲取鎖的時候, 可以設置超時時間, 如果超過了這個時間還沒拿到這把鎖, 那么就可以做其他的事情, 而不是像 synchronized 如果沒有拿到鎖會一直等待下去.
boolean tryLock ( long time , TimeUnit unit ) throws InterruptedException ;
造成超時的原因有很多種:發生了死鎖, 線程進入了死循環, 線程邏輯復雜執行慢.
到了超時時間, 那么就獲取鎖失敗, 就可以做一些記錄操作, 例如 打印錯誤日志, 發送報警郵件,提示運維人員重啟服務等等.
如下的代碼演示了 使用tryLock 來避免死鎖的案例.
線程1 如果拿到了鎖1 , 那么就在指定的800毫秒內去嘗試拿到鎖2, 如果兩把鎖都拿到了 , 那么就釋放這兩把鎖. 如果在指定的時間內, 沒有拿到鎖2 , 那么就釋放鎖1 .
線程2 與線程1相反, 先去嘗試拿到鎖2, 如果拿到了, 就去在3s內嘗試拿到鎖1, 如果拿到了, 那么就釋放鎖1和2, 如果3s內沒有拿到鎖1, 那么釋放鎖2 .
package com . thread . deadlock ; import java . util . Random ; import java . util . concurrent . TimeUnit ; import java . util . concurrent . locks . Lock ; import java . util . concurrent . locks . ReentrantLock ; /** * 類名稱:TryLockDeadlock * 類描述: 使用lock接口提供的trylock 避免死鎖 * * @author: https://javaweixin6.blog.csdn.net/ * 創建時間:2020/9/12 17:23 * Version 1.0 */ public class TryLockDeadlock implements Runnable { int flag = 1 ; //ReentrantLock 為可重入鎖 static Lock lock1 = new ReentrantLock ( ) ; static Lock lock2 = new ReentrantLock ( ) ; public static void main ( String [ ] args ) { // 創建兩個線程 給出不同的flag 並啟動 TryLockDeadlock r1 = new TryLockDeadlock ( ) ; TryLockDeadlock r2 = new TryLockDeadlock ( ) ; r1 . flag = 1 ; r2 . flag = 0 ; new Thread ( r1 ) . start ( ) ; new Thread ( r2 ) . start ( ) ; } @Override public void run ( ) { for ( int i = 0 ; i < 100 ; i ++ ) { if ( flag == 1 ) { //先獲取鎖1 再獲取鎖2 try { //給鎖1 800毫秒與獲取鎖, 如果拿到鎖, 返回true, 反之返回false if ( lock1 . tryLock ( 800 , TimeUnit . MICROSECONDS ) ) { System . out . println ( "線程1獲取到了鎖1 " ) ; //隨機的休眠 Thread . sleep ( new Random ( ) . nextInt ( 1000 ) ) ; if ( lock2 . tryLock ( 800 , TimeUnit . MICROSECONDS ) ) { System . out . println ( "線程1獲取到了鎖2 " ) ; System . out . println ( " 線程1 成功獲取了兩把鎖 " ) ; //釋放兩把鎖, 退出循環 lock2 . unlock ( ) ; lock1 . unlock ( ) ; break ; } else { System . out . println ( " 線程1嘗試獲取鎖2 失敗, 已經重試 " ) ; //釋放鎖1 lock1 . unlock ( ) ; //隨機的休眠 Thread . sleep ( new Random ( ) . nextInt ( 1000 ) ) ; } } else { System . out . println ( " 線程1 獲取鎖1失敗, 已重試 " ) ; } } catch ( InterruptedException e 