import java.util.concurrent.locks.ReentrantLock;
public class IntLock implements Runnable{
//重入锁ReentrantLock
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lock;
public IntLock(int lock){
this.lock = lock;
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
if(lock==1){
lock1.lockInterruptibly();
Thread.sleep(500);
lock2.lockInterruptibly();
}else{
lock2.lockInterruptibly();
Thread.sleep(500);
lock1.lockInterruptibly();
}
} catch (Exception e) {
// TODO: handle exception
}finally{
if(lock1.isHeldByCurrentThread()){
lock1.unlock();//释放锁
}
if(lock2.isHeldByCurrentThread()){
lock2.unlock();
}
System.out.println(Thread.currentThread().getId()+":线程退出");
}
}
public static void main(String[] args) throws InterruptedException {
IntLock r1 = new IntLock(1);
IntLock r2 = new IntLock(2);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
Thread.sleep(1000);
//t2线程被中断,放弃锁申请,释放已获得的lock2,这个操作使得t1线程顺利获得lock2继续执行下去;
//若没有此段代码,t2线程没有中断,那么会出现t1获取lock1,请求lock2,而t2获取lock2,请求lock1的相互等待死锁情况
t2.interrupt();
}
}
注释t2.interrupt();之后会陷入死锁状态,会看到控制台没有任何输出,程序一直运行,两个线程都在等待获取对方资源
ReenTrantLock,同一个线程每进入一次,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。和synchronized差别不大。在Synchronized优化以前,synchronized的性能是比ReenTrantLock差很多的,但是自从Synchronized引入了偏向锁,轻量级锁(自旋锁)后,两者的性能就差不多了,在两种方法都可用的情况下,官方甚至建议使用synchronized。
ReenTrantLock提供了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()来实现这个机制。
此外还能通过lock.tryLock(5,TimeUnit.SECONDS)来设置锁申请等待限时,此例就是限时等待5秒获取锁
ReenTrantLock还能进行公平锁设置他有如下构造函数
public ReentrantLock(boolean fair)
当fair为true时,锁是公平的,公平锁一大特点就是不会产生饥饿现象。所谓的公平锁就是先等待的线程先获得锁。但公平锁性能相对低下,默认情况锁是非公平的。