sp; }
System.out.println(Thread.currentThread().getName() + "需要B锁!!!");
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "B锁获取成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}, "Thread1");
Thread thread2 = new Thread(new Runnable() {
public void run() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "获取B锁 ing!");
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + "睡眠500ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
System.out.println(Thread.currentThread().getName() + "需要A锁!!!");
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + "A锁获取成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}, "Thread1");
thread1.start();
thread2.start();
}
}
运行结果如下:
可以看到显示锁Lock是可以避免死锁的。
注意:Lock接口规范形式。这种模式在某种程度上比使用内部锁更加复杂:锁必须在finally块中释放。另一方面,如果锁守护的代码在try块之外抛出了异常,它将永远都不会被释放了;如果对象
能够被置于不一致状态,可能需要额外的try-catch,或try-finally块。(当你在使用任何形式的锁时,你总是应该关注异常带来的影响,包括内部锁)。
忘记时候finally释放Lock是一个定时炸弹。当不幸发生的时候,你将很难追踪到错误的发生点,因为根本没有记录锁本应该被释放的位置和时间。这就是ReentrantLock不能完全替代synchronized的原因:它更加危险,
因为当程序的控制权离开守护的块,不会自动清除锁。尽管记得在finally块中释放锁并不苦难,但忘记的可能仍然存在。
sy
可轮询的和可定时的锁请求
可定时