可中断锁是指抢占过程可以被中断的锁,JUC的显式锁(如ReentrantLock)是一个可中断锁。不可中断锁是指抢占过程不可以被中断的锁,如Java的synchronized内置锁就是一个不可中断锁。
锁的可中断抢占:
在JUC的显式锁Lock接口中,有以下两个方法可以用于可中断抢占:
(1)lockInterruptibly()
可中断抢占锁抢占过程中会处理Thread.interrupt()中断信号,如果线程被中断,就会终止抢占并抛出InterruptedException异常。
(2)tryLock(long timeout,TimeUnit unit)
阻塞式“限时抢占”(在timeout时间内)锁抢占过程中会处理Thread.interrupt()中断信号,如果线程被中断,就会终止抢占并抛出InterruptedException异常。
下面是调用lockInterruptibly()方法进行可中断抢锁的一个简单案例,具体代码如下:
public class LockTest {
private int sum;
@Test
public void testInterruptLock() throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Runnable target = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始抢占锁...");
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"抢占被中断,抢锁失败...");
e.printStackTrace();
return;
}
try{
System.out.println(Thread.currentThread().getName()+"抢到了锁,同步执行1秒");
Thread.sleep(1000);
sum++;
if(Thread.currentThread().isInterrupted()){
System.out.println("同步被中断");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
};
Thread t1 = new Thread(target,"thread-1");
Thread t2 = new Thread(target,"thread-2");
t1.start();
t2.start();
Thread.sleep(100);
System.out.println("等待100ms,中断两个线程");
t1.interrupt();
t2.interrupt();
Thread.sleep(Integer.MAX_VALUE);
}
}
执行结果: 从该例子可以看出:
-
如果抢占过程收到由Thread.interrupt()方法发出的线程中断信号,lockInterruptibly()方法就会抛出InterruptedException。 -
如果此线程处于阻塞状态,就会立马退出阻塞,并抛出InterruptedException异常,线程就可以通过捕获InterruptedException来做一定的处理,然后让线程退出。更确切地说,如果线程被Object.wait()、Thread.join()和Thread.sleep()三种方法之一阻塞,此时调用该线程的interrupt()方法,该线程将抛出一个InterruptedException中断异常,从而提早终结被阻塞状态。
|