ReentrantLock锁相关方法

目录

ReentrantLock锁

Lock接口的实现类

ReentrantLock即可重入锁

效果同synchronized关键字

ReentrantLock的方法

public String toString()

返回标识此锁的字符串,以及其锁状态。括号中的状态包括字符串 “Unlocked” 或字符串 “Locked by”,后跟拥有线程的名称。

public int getWaitQueueLength(Condition condition)

返回在与该锁关联的给定条件下等待的线程数的估计值。请注意,由于超时和中断可能随时发生,因此该估计仅用作实际服务员人数的上限。此方法旨在用于监视系统状态,而不是用于同步控制。

public boolean hasWaiters(Condition condition)

查询是否有任何线程正在等待与此锁关联的给定条件。请注意,由于超时和中断可能随时发生,因此真实的返回并不能保证将来的信号会唤醒任何线程。此方法主要设计用于监视系统状态。

public final boolean hasQueuedThread(Thread thread)

查询给定线程是否正在等待获取此锁。请注意,由于取消可能随时发生,因此真正的返回并不能保证该线程将永远获得此锁。此方法主要设计用于监视系统状态。

public final int getQueueLength()

返回等待获取此锁的线程数的估计值。该值只是一个估计值,因为在该方法遍历内部数据结构时,线程数可能会动态变化。此方法旨在用于监视系统状态,而不是用于同步控制。

public final boolean hasQueuedThreads()

查询是否有任何线程在等待获取此锁。请注意,由于取消可能随时发生,因此真正的返回并不能保证任何其他线程都将获得此锁。此方法主要设计用于监视系统状态。

public final boolean isFair()

如果此锁的公平设置为true,则返回true

public boolean isLocked()

查询此锁是否由任何线程持有。此方法旨在用于监视系统状态,而不是用于同步控制。

public int getHoldCount()

查询当前线程对此锁的保留数。
线程对每个锁定动作都有一个锁定,而解锁动作不匹配。

public boolean isHeldByCurrentThread()

查询此锁是否由当前线程持有。
类似于内置监视器锁的Thread.holdsLock(Object) 方法,该方法通常用于调试和测试。

public ReentrantLock()

创建ReentrantLock的实例。这相当于使用ReentrantLock(false)。

public ReentrantLock(boolean fair)

使用给定的公平策略创建ReentrantLock实例。(true表示公平锁策略)

ReentrantLockTest测试

用于测试的线程

Thread t1 = new Thread(() -> {
            for (int i = 0; i < 2; i++) {
                try {
                    lock.lock();
                    System.out.println("t1获取锁:lock.lock()");
                    lock.lock();//每次循环重复获取锁2次
                    System.out.println("t1获取锁:lock.lock()");
                } finally {
                    System.out.println("t1释放锁:lock.unlock()");
                    lock.unlock();//每次循环只释放一次锁
                }
            }
            System.out.println("t1当前对lock的获取次数:" + lock.getHoldCount());
        });

        Thread t2 = new Thread(() -> {
            try {
                System.out.println("t2线程 lock.lock()");
                lock.lock();
                System.out.println("t2获取到锁:lock");
            } finally {
                lock.unlock();
            }
        });

        Thread t3 = new Thread(() -> {
            try {
                System.out.println("t3使用trylock()尝试获取锁");
                if (lock.tryLock())
                    System.out.println("t3线程获取了锁");
                else
                    System.out.println("t3获取锁失败");

            } finally {
                if (lock.isHeldByCurrentThread())
                    lock.unlock();
                else
                    System.out.println("t3没有获取到锁 不需要执行unlock()");
            }
        });

        Thread t4 = new Thread(() -> {
            try {
                System.out.println("t4使用lockInterruptibly()尝试获取锁");
                lock.lockInterruptibly();
                System.out.println("t4获取到了锁");
            } catch (InterruptedException e) {
                System.out.println("t4在等待lock释放时被中断");
                e.printStackTrace();
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                } else {
                    System.out.println("t4没有获取到锁 不需要执行unlock()");
                }
            }
        });

t1测试

System.out.println("\nt1线程启动");
        t1.start();
        Thread.sleep(100);

在这里插入图片描述

正确释放重入锁

t1线程此时并没有释放锁
ReentrantLock的机制为:

如果一个线程获取了此锁
则可以在后续多次重复获取
但也需要相同次数的释放
才能正确的释放锁

获取当前的重入次数

t1线程获取锁共4次
释放锁2次
剩余2次获取没有释放

在线程循环外通过lock.getHoldCount()得到了线程t1对lock的重入次数

t1t2测试

        System.out.println("\nt1线程启动");
        t1.start();
        Thread.sleep(100);
        System.out.println(lock.isLocked());

        System.out.println("\nt2线程启动");
        t2.start();
        Thread.sleep(100);

在这里插入图片描述

使用islocked()方法检测锁状态

如果锁已经被某个线程获取
islocked方法返回true
否则返回false

因为线程t1没有正确释放重入锁 t2没有获取到锁

t1t3测试

System.out.println("\nt1线程启动");
        t1.start();
        Thread.sleep(100);
System.out.println("\nt3线程启动");
        t3.start();
        Thread.sleep(100);

在这里插入图片描述

使用trylock方法尝试获取锁

trylock尝试获取锁
如果获取成功 返回true
如果获取失败 返回false 且不会阻塞等待锁释放

使用isHeldByCurrentThread方法检测当前线程是否持有锁

如果当前线程持有此锁返回true
如果当前线程不持有锁返回false

不持有锁时调用unlock方法

如果线程在没有获取到此锁的情况下使用了此锁unlock方法
会抛出illegalMonitorStateException

t3中
在释放锁之前使用isHeldByCurrentThread检测
避免在不持有锁时释放锁

t1t4测试

        System.out.println("\nt1线程启动");
        t1.start();
        Thread.sleep(100);
        System.out.println("\nt4线程启动");
        t4.start();
        Thread.sleep(100);
        t4.interruput();

在这里插入图片描述

使用lockInterruptbly()尝试获取锁

当获取成功 效果同lock()
当获取失败 阻塞等待锁释放 但此线程在阻塞期间可以响应中断

中断因为lockInterruptbly()阻塞的线程

当线程因为lockInterruptbly()阻塞时
如果收到中断请求
会抛出interruptedException

效果同sleep wait期间收到中断请求
可以捕获异常进行中断处理

t1t2t3t4测试

System.out.println("\nt1线程启动");
        t1.start();
        Thread.sleep(100);

        System.out.println("\nt2线程启动");
        t2.start();
        Thread.sleep(100);

        System.out.println("\nt3线程启动");
        t3.start();
        Thread.sleep(100);

        System.out.println("\nt4线程启动");
        t4.start();
        Thread.sleep(100);

        System.out.println("\nlock锁的检测方法:");
        System.out.println("是否有线程在等待lock锁:"+lock.hasQueuedThreads());
        System.out.println("有多少线程在等待lock锁:"+lock.getQueueLength());
        System.out.println("t2线程是否在等待lock锁:"+lock.hasQueuedThread(t2));
        System.out.println("lock是否为公平锁:"+lock.isFair());

在这里插入图片描述

使用hasQueuedThreads方法检测是否有线程在等待此锁

如果返回true说明有线程在等待此锁
否则返回false

使用getQueueLength方法检测等待此锁的线程数量

返回的整数代表等待此锁的线程数量
此处t2 t4线程在等待锁
t3线程使用trylock()没有获取到锁 已经执行else路径的代码退出 没有阻塞等待lock释放

使用hasQueuedThread方法检测指定线程是否在等待此锁

如果返回true 代表此线程正在等待此锁释放
如果返回false代表此线程没在等待此锁

使用isFair检测此锁是否为公平锁

如果返回true 代表此锁是公平锁
如果返回false代表此锁不是公平锁

公平锁即 请求获取此锁的线程按请求顺序依次获得锁
非公平锁即 所有请求获取此锁的线程随机竞争

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ReentrantLockJava中的一个可重入,它提供了与synchronized关键字类似的功能,但更加灵活和强大。下面是一些与ReentrantLock相关的面试题及其答案: 1. 什么是可重入? 可重入是指同一个线程可以多次获得同一个,而不会造成死。ReentrantLock就是一个可重入。 2. ReentrantLock相对于synchronized关键字有什么优势? 相对于synchronized关键字,ReentrantLock提供了更多的功能和灵活性。它可以实现公平和非公平,支持多个条件变量,可以中断等待的线程,还可以尝试获取等。 3. ReentrantLock如何实现可重入性? ReentrantLock通过记录持有的线程和持有次数来实现可重入性。当一个线程再次获取已经持有的时,它的持有次数会增加,当释放时,持有次数会减少,只有当持有次数为0时,其他线程才能获取该。 4. ReentrantLock如何实现公平性和非公平性? ReentrantLock可以通过构造函数来指定是公平还是非公平。公平会按照线程请求的顺序来获取,而非公平则允许插队,可能会导致某些线程一直获取不到。 5. ReentrantLock如何实现条件变量? ReentrantLock提供了Condition接口来支持条件变量。通过调用ReentrantLock的newCondition()方法可以创建一个Condition对象,然后可以使用该对象的await()、signal()和signalAll()方法来实现线程的等待和唤醒。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值