lock()
兩個線程都使用lock獲取鎖,如果線程A獲取到了鎖,線程B只能等待,對線程B調用interrupt()方法不能中斷線程B的等待過程。
tryLock()
使用lock獲取鎖,如果線程A獲取到了鎖,線程A返回true,線程B直接返回false。可以傳入時間參數,表示拿不到鎖等待一段時間,這段時間內還是拿不到就返回false。
lockInterruptibly()
兩個線程都使用lockInterruptibly獲取鎖,如果線程A獲取到了鎖,線程B只能等待,對線程B調用interrupt()方法能夠中斷線程B的等待過程。
案例
如下示例中,t0得到了鎖,t1等待。在t1等待時,調用t1.interrupt(),中斷t1的等待。
public class ReentrantLockDemo {
private Lock lock = new ReentrantLock();
public void test() {
String name = Thread.currentThread().getName();
try {
System.out.println(name + " 嘗試獲取鎖");
lock.lockInterruptibly();
Thread.sleep(1000);
System.out.println(name + " 得到鎖");
} catch (InterruptedException e) {
System.out.println(name + " InterruptedException異常");
} finally {
try {
lock.unlock();
System.out.println(name + " 嘗試釋放鎖");
} catch (Exception e) {
System.out.println(name + " : 釋放鎖失敗(未獲取鎖的線程調用unlock)");
}
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo lock = new ReentrantLockDemo();
Thread t0 = new Thread(
lock::test
);
Thread t1 = new Thread(
lock::test
);
t0.start();
Thread.sleep(10);
t1.start();
Thread.sleep(100);
// 中斷等待中的t1的線程
t1.interrupt();
}
}
運行結果:
Thread-0 嘗試獲取鎖
Thread-1 嘗試獲取鎖
Thread-1 InterruptedException異常
Thread-1 : 釋放鎖失敗(未獲取鎖的線程調用unlock)
Thread-0 得到鎖
Thread-0 嘗試釋放鎖
如果使用lock()方法獲取鎖,線程不會被中斷。將lock.lockInterruptibly()改爲lock.lock()。
運行結果:
Thread-0 嘗試獲取鎖
Thread-1 嘗試獲取鎖
Thread-0 得到鎖
Thread-0 嘗試釋放鎖
Thread-1 lockInterruptibly的InterruptedException異常
Thread-1 嘗試釋放鎖
從案例中可以看出,使用lockInterruptibly方法時候會出現 釋放鎖失敗(未獲取鎖的線程調用unlock)的異常,而使用lock方法時不會出現這個異常。
原因
使用lockInterruptibly獲取鎖時,當它處於等待階段時直接被中斷,沒有獲取到鎖,所以調用unlock會發生異常。而使用lock獲取鎖時,當它處於等待階段時,中斷不了,等到線程0結束後,線程1得到鎖才被中斷,所以調用unlock時不會發生異常。