> 文档中心 > 并发类编程—ReentrantLock(可重入锁)

并发类编程—ReentrantLock(可重入锁)


1、概念

ReentantLock继承接口 Lock 并实现了接口中定义的方法,他是一种可重入锁,除了能完成synchronized 所能完成的所有工作外,还提供了中断锁、定时锁等避免多线程死锁的方法。

ReentantLock可以创建多个Condition条件,通过await()和signal()方法实现等待和唤醒。

2、主要方法

  1. void lock(): 执行此方法时, 如果锁处于空闲状态, 当前线程将获取到锁. 相反, 如果锁已经被其他线程持有, 将一直等待直到当前线程获取到锁.
  2. boolean tryLock():如果锁可用, 则获取锁, 并立即返回 true, 否则返回 false. 该方法和
    lock()的区别在于, tryLock()只是"试图"获取锁, 如果锁不可用, 不会导致当前线程被挂起,当前线程仍然继续往下执行代码.
  3. void unlock():当前线程将释放持有的锁. 锁只能由持有线程释放.
  4. getHoldCount() :查询当前线程保持此锁的次数,也就是执行此线程执行lock方法的次数。
  5. getQueueLength():返回正等待获取此锁的线程估计数,比如启动 10 个线程,1 个线程获得锁,此时返回的是 9.
  6. hasQueuedThread(Thread thread):查询给定线程是否等待获取此锁
  7. hasQueuedThreads():是否有线程等待此锁
  8. isFair():该锁是否公平锁
  9. isLock():此锁是否有任意线程占用
  10. lockInterruptibly():如果当前线程未被中断,获取锁
  11. 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();    }}

效果:
并发类编程—ReentrantLock(可重入锁)