重入锁ReentrantLock类似于synchronized,都可以让多个线程对临界区资源的访问进行控制,但重入锁需要手动释放锁,正是这样,重入锁更加的灵活;介绍重入锁防死锁的两种方式:
1.中断响应 lockInterruptibly():
import java.util.concurrent.locks.ReentrantLock;
/**
* lockInterruptibly 可以响应中断
*/
public class TestLockInterruptibly implements Runnable{
private static ReentrantLock r1 = new ReentrantLock();
private static ReentrantLock r2 = new ReentrantLock();
private int i;
public TestLockInterruptibly(int i) {
this.i = i;
}
@Override
public void run(){
if(i == 0){
try {
r1.lockInterruptibly();
Thread.sleep(1000);
System.out.println("r1xxx start...");
try {
r2.lockInterruptibly();
System.out.println("r2xxx start....");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
if(r2.isHeldByCurrentThread()){
r2.unlock();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
if(r1.isHeldByCurrentThread()){
r1.unlock();
}
}
}else{
try {
r2.lockInterruptibly();
Thread.sleep(1000);
System.out.println("r2 start...");
try {
r1.lockInterruptibly();
System.out.println("r1 start...");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
if(r1.isHeldByCurrentThread()){
r1.unlock();
}
}
} catch (InterruptedException e) {
System.out.println("被中断");
}finally{
if(r2.isHeldByCurrentThread()){
r2.unlock();
}
}
}
}
public static void main(String[] args){
TestLockInterruptibly k1 = new TestLockInterruptibly(0);
TestLockInterruptibly k2 = new TestLockInterruptibly(1);
Thread t1 = new Thread(k1, "t1");
Thread t2 = new Thread(k2, "t2");
t1.start();
t2.start();
t2.interrupt();
}
}
控制台:
被中断
r1xxx start...
r2xxx start....
2.锁申请 tryLock():
import java.util.concurrent.locks.ReentrantLock;
/**
* tryLock() 如果申请到锁 立即返回true 否则返回false
* tryLock(5, TimeUnit.Seconds) 可以接参数 一定时间内申请到锁
* 返回true 否则返回false
*/
public class TestTryLock implements Runnable{
private static ReentrantLock r1 = new ReentrantLock(); //此处必须是静态的 否则 main两个实例获取的不是一把锁
private static ReentrantLock r2 = new ReentrantLock();
private int i;
public TestTryLock(int i ){
this.i = i;
}
@Override
public void run(){
if(i == 0) {
try {
if (r1.tryLock()) {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "done r1 work..");
try {
if (r2.tryLock()) {
System.out.println(Thread.currentThread().getName() + "done r2 work...");
return;
}
} finally {
if (r2.isHeldByCurrentThread()) {
r2.unlock();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (r1.isHeldByCurrentThread()) {
r1.unlock();
}
}
}else {
try {
if (r2.tryLock()) {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "done r2 work ...");
try {
if (r1.tryLock()) {
System.out.println(Thread.currentThread().getName() + "done r1 work...");
return;
}
} finally {
if (r1.isHeldByCurrentThread()) {
r1.unlock();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (r2.isHeldByCurrentThread()) {
r2.unlock();
}
}
}
}
public static void main(String[] args){
Thread t1 = new Thread(new TestTryLock(0), "t1");
Thread t2 = new Thread(new TestTryLock(1), "t2");
t1.start();
t2.start();
}
}
控制台:
t1done r1 work..
t2done r2 work ...
t2done r1 work...
--案例来源于java高并发程序设计