前面讲解了ReentrantLock加锁和解锁的原理实现,但是没有阐述它的可重入、可打断以及超时获取锁失败的原理,本文就重点讲解这三种情况。建议大家先看下这篇文章了解下ReentrantLock加锁的基本原理,图解ReentrantLock公平锁和非公平锁实现原理。,可重入是指一个线程如果获取了锁,那么它就是锁的主人,那么它可以再次获取这把锁,这种就是理解为重入,简而言之,可以重复获取同一把锁,不会造成阻塞,举个例子如下:,,那你知道是怎么实现的吗?,概述的文章中已经讲解了ReentrantLock整个的加锁和解锁的过程,可重入实现就在其中,这里着重关注下申请锁的方法tryAcquire,最终会调用nonfairTryAcquire方法。,,如果已经有线程获得了锁, 并且占用锁的线程是当前线程, 表示【发生了锁重入】,上图的1步骤,计算出冲入的次数nextc等于当前次数+新增次数,acquires等于1,更新 state 的值,这里不使用 cas 是因为当前线程正在持有锁,所以这里的操作相当于在一个管程内, 然后返回ture,表明再次申请锁成功。,ReentrantLock相比于synchronized加锁一大优势是可打断,那么什么是可打断呢?ReentrantLock通过lockInterruptibly()加锁,如果一直获取不到锁,可以通过调用线程的interrupt()提前终止线程。举个例子:,,接下来我们看看它的实现原理。,先判断一次线程是否中断了,是的话,直接抛出中断异常。,如果没有获取锁,调用doAcquireInterruptibly()方法。,addWaiter将当前线程封装成节点,加入到队列中。,shouldParkAfterFailedAcquire()方法判断如果前一个节点的等待状态时-1,则返回true,表示当前线程需要阻塞。,parkAndCheckInterrupt()方法是阻塞线程,返回true,表示线程被中断了,抛出InterruptedException异常。,最后调用cancelAcquire()方法,将当前节点状态设置为cancel取消状态。,ReentrantLock还具备锁超时的能力,调用tryLock(long timeout, TimeUnit unit)方法,在给定时间内获取锁,获取不到就退出,这也是synchronized没有的功能。,那这个原理实现是什么样的呢?,如果nanosTimeout小于0,表示到了指定时间没有获取锁成功,返回false,如果 nanosTimeout 大于spinForTimeoutThreshold,值为1000L,进行阻塞。因为时间太短阻塞没有意义,否则直接自旋会好点。,本文主要从使用到原理讲解了ReentrantLock锁的可重入、可打断和锁超时的特性,希望对大家有帮助。
文章版权声明
1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/16482.html
2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈
3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)
4 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别