ReentrantLock源码分析

对于ReentrantLock我相信对于做Java的朋友应该不会陌生,它是juc并发工具包下面的一个并发工具类,对于一些存在资源竞争的情况下,我们经常会用到,和java关键字synchronized不同的是,ReentrantLock提供了更好的灵活性以及实现了公平和非公平锁,还有超时的概念,那ReentrantLock底层是如何实现的呢,那我们通过源码去深入了解他实现的原理,我们才能更好的使用。

首先我们看我们平常使用ReentrantLock的例子

 

这里通过构造方法初始化了ReentrantLock,我们点击进入

ReentrantLock里面维护了一个Sync的内部类,Sync继承了AbstractQueuedSynchronizer抽象同步器,这个AbstractQueuedSynchronizer定义了锁的一些基本架构,juc大部分的同步工具类都是基于这个类实现的,这里就不做过多的阐述了,后面单独出来讲讲这个抽象同步队列器,从上面的代码我们可以看到通过ReentrantLock的构造方法,初始化成员变量Sync的是其子类之NonfairSync这个类是实现非公平的锁的功能,我们从最开始的加锁的代码跟进

加锁的时候会调用的sync.lock()方法,前面通过构造方法初始化的时候这个sync的成员变量对应的是NonfairSync这个实现类,所以这里调用的是NonfairSync的lock方法

 

 一进来的时候通过compareAndSetState这个cas操作,看能不能将AQS里面维护的一个int类型的state成员变量,如果能够成功将它的值改为1,就代表获取锁成功,并且将持有锁的线程应用赋值为当前线程,如果失败则调用acquire(1)这个分支,我们继续跟进源码

这里首先会再一次去尝试获取一下锁资源, 

 

这里最终会调用到nonfairTryAcquire这个方法里面,这里面主要的逻辑就是,先获取这个全局变量state的值如果是0代码锁资源还没有被其他线程获取,直接通过cas操作,如果能够把state从0变到1,代表获取锁成功,直接返回true的标识,第二种情况state不为0的情况,并且当前进入的线程正好是锁的持有者,就直接将state加1操作,这里就是实现可重入锁的关键代码逻辑,其余的情况返回false,我们将代码返回到之前调用之初的地方

 这个tryAcquire方法会最终调用到上面nonfairTryAcquire方法里面,如果nonfairTryAcquire返回false代表获取锁资源失败,这里取反操作第一个条件为true,就会进入acquireQueued(addWaiter(Node.EXCLUSIVE), arg)代码里面,这里会先调用addWaiter方法

 

 首先会用当前线程初始化一个Node对象,然后将tail赋值给pred,第一次进来的时候pred肯定为空,就会走enq(node)代码逻辑,继续点进去看看这个enq方法

 很明显这里通过一个自旋操作(也就是死循环),第一次进来的时候因为tail为空,肯定会走到上面的分支,然后通过cas操作设置一个头节点对象,这里head成员变量就有值不为空了,最后赋值给tail尾节点,第一轮循环结束,进入第二轮循环的是,此时Node t = tail 此时的t就不为空了,会走else里面的代码逻辑,先是将当前传入节点的前驱节点指向头节点,然后通过cas操作将当前节点加入到队尾部,然后直接return退出自旋,最终返回到调用的初始地方

 

这里最终会调用到acquireQueued这个方法里面会首先判断当前节点的前驱节点是否为头节点,如果是头节点的话,会尝试再去获取一次锁,如果获取成功就直接结束,如果获取锁资源失败就会接着往下面走

if (shouldParkAfterFailedAcquire(p, node) &&
    parkAndCheckInterrupt())
    interrupted = true;

 这里首先会进入shouldParkAfterFailedAcquire这个方法,

这段代码的作用就是将成员变量waitStatus从0改到signal -1的状态,后续能否唤醒线程的条件,然后返回true结束,最终走完返回到

因为最终返回的true,这里会进入parkAndCheckInterrupt这段代码里面

 

 很明显这里就是调用的java工具类LockSupport的park方法,进行阻塞,到这里整个加锁的逻辑就已经结束了,后面再讲讲是当前线程释放资源后是如何唤起阻塞线程的

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值