lockInterruptibly() 方法的作用:如果当前线程未被中断则获得锁,如果当前线程被中断则出现异常。
package com.wkcto.lock.reentrant;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* lockInterruptibly() 方法的作用:如果当前线程未被中断则获得锁,如果当前线程被中断则出现异常.
*/
public class Test05 {
static class Servier{
private Lock lock = new ReentrantLock(); //定义锁对象
public void serviceMethod(){
try {
// lock.lock(); //获得锁定,即使调用了线程的interrupt()方法,也没有真正的中断线程
lock.lockInterruptibly(); //如果线程被中断了,不会获得锁,会产生异常
System.out.println(Thread.currentThread().getName() + "-- begin lock");
//执行一段耗时的操作
for (int i = 0; i < Integer.MAX_VALUE; i++) {
new StringBuilder();
}
System.out.println( Thread.currentThread().getName() + " -- end lock");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println( Thread.currentThread().getName() + " ***** 释放锁");
lock.unlock(); //释放锁
}
}
}
public static void main(String[] args) throws InterruptedException {
Servier s = new Servier();
Runnable r = new Runnable() {
@Override
public void run() {
s.serviceMethod();
}
};
Thread t1 = new Thread(r);
t1.start();
Thread.sleep(50);
Thread t2 = new Thread(r);
t2.start();
Thread.sleep(50);
t2.interrupt(); //中断t2线程
}
}
对于synchronized内部锁来说,如果一个线程在等待锁,只有两个结果:要么该线程获得锁继续执行;要么就保持等待。
对于ReentrantLock可重入锁来说,提供另外一种可能,在等待锁的过程中,程序可以根据需要取消对锁的请求。
package com.wkcto.lock.reentrant;
import com.wkcto.pipestream.Test2;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 通过ReentrantLock锁的lockInterruptibly()方法避免死锁的产生
*/
public class Test06 {
static class IntLock implements Runnable{
//创建两个ReentrantLock 锁对象
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lockNum; //定义整数变量,决定使用哪个锁
public IntLock(int lockNum) {
this.lockNum = lockNum;
}
@Override
public void run() {
try {
if ( lockNum % 2 == 1){ //奇数,先锁1,再锁2
lock1.lockInterruptibly();
System.out.println(Thread.currentThread().getName() + "获得锁1,还需要获得锁2");
Thread.sleep(new Random().nextInt(500));
lock2.lockInterruptibly();
System.out.println(Thread.currentThread().getName() + "同时获得了锁1与锁2....");
}else { //偶数,先锁2,再锁1
lock2.lockInterruptibly();
System.out.println(Thread.currentThread().getName() + "获得锁2,还需要获得锁1");
Thread.sleep(new Random().nextInt(500));
lock1.lockInterruptibly();
System.out.println(Thread.currentThread().getName() + "同时获得了锁1与锁2....");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if ( lock1.isHeldByCurrentThread()) //判断当前线程是否持有该锁
lock1.unlock();
if (lock2.isHeldByCurrentThread())
lock2.unlock();
System.out.println( Thread.currentThread().getName() + "线程退出");
}
}
}
public static void main(String[] args) throws InterruptedException {
IntLock intLock1 = new IntLock(11);
IntLock intLock2 = new IntLock(22);
Thread t1 = new Thread(intLock1);
Thread t2 = new Thread(intLock2);
t1.start();
t2.start();
//在main线程,等待3000秒,如果还有线程没有结束就中断该线程
Thread.sleep(3000);
//可以中断任何一个线程来解决死锁, t2线程会放弃对锁1的申请,同时释放锁2, t1线程会完成它的任务
if (t2.isAlive()){ t2.interrupt();}
}
}