📑前言
本文主要是【JUC】——JUC之可重入锁的文章,如果有什么需要改进的地方还请大佬指出⛺️
🎬作者简介:大家好,我是听风与他🥇
☁️博客首页:CSDN主页听风与他
🌄每日一句:狠狠沉淀,顶峰相见
目录
- 📑前言
- 可重入锁
- 📑文章末尾
可重入锁
-
ReentrantLock,其实是锁的一种,叫做可重入锁,可重入:简单来说,就是同一个线程,可以反复进行加锁操作。
public static void main(String[] args) throws InterruptedException { ReentrantLock lock = new ReentrantLock(); lock.lock(); lock.lock(); //连续加锁2次 new Thread(() -> { System.out.println("线程2想要获取锁"); lock.lock(); System.out.println("线程2成功获取到锁"); }).start(); lock.unlock(); System.out.println("线程1释放了一次锁"); TimeUnit.SECONDS.sleep(1); lock.unlock(); System.out.println("线程1再次释放了一次锁"); //释放两次后其他线程才能加锁 }
输出结果为
线程1释放了一次锁 线程2想要获取锁 线程1再次释放了一次锁 线程2成功获取到锁
可以看到,主线程连续进行了两次加锁操作(此操作是不会被阻塞的),在当前线程持有锁的情况下继续加锁不会被阻塞,并且,加锁几次,就必须要解锁几次,否则此线程依旧持有锁。我们可以使用getHoldCount()方法查看当前线程的加锁次数:
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
lock.lock();
lock.lock();
System.out.println("当前加锁次数:"+lock.getHoldCount()+",是否被锁:"+lock.isLocked());
TimeUnit.SECONDS.sleep(1);
lock.unlock();
System.out.println("当前加锁次数:"+lock.getHoldCount()+",是否被锁:"+lock.isLocked());
TimeUnit.SECONDS.sleep(1);
lock.unlock();
System.out.println("当前加锁次数:"+lock.getHoldCount()+",是否被锁:"+lock.isLocked());
}
打印结果:
当前加锁次数:2,是否被锁:true
当前加锁次数:1,是否被锁:true
当前加锁次数:0,是否被锁:false
- 当锁不再被任何线程持有时,值为0,并且通过isLocked()方法查询结果为false。
如果存在线程持有当前的锁,那么其他线程在获取锁时,暂时会进入到等待队列,我们可以通过getQueueLength()
方法获取等待中线程数量的预估值。
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
lock.lock();
Thread t1 = new Thread(lock::lock), t2 = new Thread(lock::lock);;
t1.start();
t2.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("当前等待锁释放的线程数:"+lock.getQueueLength());
System.out.println("线程1是否在等待队列中:"+lock.hasQueuedThread(t1));
System.out.println("线程2是否在等待队列中:"+lock.hasQueuedThread(t2));
System.out.println("当前线程是否在等待队列中:"+lock.hasQueuedThread(Thread.currentThread()));
}