1、概念
ReentantLock继承接口 Lock 并实现了接口中定义的方法,他是一种可重入锁,除了能完成synchronized 所能完成的所有工作外,还提供了中断锁、定时锁等避免多线程死锁的方法。
ReentantLock可以创建多个Condition条件,通过await()和signal()方法实现等待和唤醒。
2、主要方法
- void lock(): 执行此方法时, 如果锁处于空闲状态, 当前线程将获取到锁. 相反, 如果锁已经被其他线程持有, 将一直等待直到当前线程获取到锁.
- boolean tryLock():如果锁可用, 则获取锁, 并立即返回 true, 否则返回 false. 该方法和
lock()的区别在于, tryLock()只是"试图"获取锁, 如果锁不可用, 不会导致当前线程被挂起,当前线程仍然继续往下执行代码. - void unlock():当前线程将释放持有的锁. 锁只能由持有线程释放.
- getHoldCount() :查询当前线程保持此锁的次数,也就是执行此线程执行lock方法的次数。
- getQueueLength():返回正等待获取此锁的线程估计数,比如启动 10 个线程,1 个线程获得锁,此时返回的是 9.
- hasQueuedThread(Thread thread):查询给定线程是否等待获取此锁
- hasQueuedThreads():是否有线程等待此锁
- isFair():该锁是否公平锁
- isLock():此锁是否有任意线程占用
- lockInterruptibly():如果当前线程未被中断,获取锁
- tryLock(long timeout TimeUnit unit):在给定等待时间内尝试获取锁,获取获得到则返回true,没有获取则返回flase.
3、Condition使用
Condition用时等待/通知,即当线程进行等待后,需要通知才能继续执行。
await()进入等待,signal()唤醒绑定Condition的第一个线程,signalAll()唤醒绑定Condition的所有线程。
比如: A、B两个线程轮流打印数字
public class Test {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition conditionA = lock.newCondition();
Condition conditionB = lock.newCondition();
new Thread(() -> {
try {
for (int a = 1; a <= 10; a++) {
// 上锁
lock.lock();
System.out.println("线程A打印数字:" + a);
// 唤醒其他线程
conditionB.signalAll();
// 自身进入等待状态
conditionA.await();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "conditionA").start();
new Thread(() -> {
try {
for (int a = 1; a <= 10; a++) {
// 上锁
lock.lock();
System.out.println("线程B打印数字:" + a);
// 唤醒其他线程
conditionA.signalAll();
// 自身进入等待状态
conditionB.await();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}, "conditionB").start();
}
}
效果: