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时不会发生异常。