ReentrantLock可重入锁,可以说是synchronized的加强版,它相比synchronized有以下特点
- 可中断
- 可以设置超时时间
- 可以设置为公平锁
- 支持多个条件变量
想要锁可打断需要使用lockInterruptibly方法,这样线程调用interrupt方法后就可以被打断,是防止死锁的一种方式
public void testInterrupt() throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Thread thread = new Thread(() -> {
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
log.info("被打断,退出");
return;
}
try {
log.info("获取到锁,处理业务");
} finally {
log.info("释放锁");
lock.unlock();
}
});
lock.lock();
thread.start();
Thread.sleep(1000);
thread.interrupt();
}
lock.tryLock尝试获取锁,可以设置超时时间,超过时间就直接返回了,根据返回值来判断是否拿到锁,此方式也可以防止死锁
public void testTryLock() throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Thread thread = new Thread(() -> {
try {
//不设置时间的话没有获取到锁立即返回
if (!lock.tryLock(1, TimeUnit.SECONDS)) {
log.info("没有获取到锁,退出");
return;
}
} catch (InterruptedException e) {
log.info("没有获取到锁,退出");
return;
}
try {
log.info("获取到锁,处理业务");
} finally {
log.info("释放锁");
lock.unlock();
}
});
lock.lock();
thread.start();
Thread.sleep(2000);
lock.unlock();
}
ReentrantLock默认是非公平的,也就是锁队列中谁获取到锁跟排队时间没关系,完全随机的,实现公平锁很简单,构造方法里面传个true就行,但是公平锁会降低并发并发度,用的比较少
ReentrantLock lock = new ReentrantLock(true);
看一个案例,工作室只能容纳一个人工作,这个可以用锁来实现,老李需要斧头才能工作,这是他进入工作室,也就是获取到锁后,发现没斧头,不能工作,如果还呆在工作室,别人就没法进入,所以就把他安排到休息室,等有斧头了再让他工作。