深入了解ReentrantLock可重入锁

深入了解ReentrantLock可重入锁

最早当我们遇到线程不安全的问题时,脑子第一想到的是synchronize关键字进行加锁机制,保证在多线程情景中数据操作的正确性,但是从java1.5开始它又给我们提供了ReentrantLock可重入锁机制,为我们在多样化的业务场景中保驾护航!

可重入锁的实现

可重入锁分为两种锁,公平锁和非公平锁,简单解释一下公平锁和非公平锁的含义,在公平锁的环境下大家竞争同一个资源的时候是有秩序的,要有一个先来后到要排队,不能一窝蜂的全涌上去抢;但是在非公平锁的环境下大家竞争同一个资源的时候就不那么讲规矩,也不和你论资排辈了,大家等资源空闲的时候一涌而上,谁抢到就是谁的,周而复始,下面我们就从ReentranLock的源码中看一下java是怎么实现这两种方式的。

ReentranLock继承关系

深入了解ReentrantLock可重入锁_第1张图片

这个图是我用idea的show diagram方法和qq截图将FairSync补上的,大家如果知道idea有比show diagram更好的方法的话,欢迎给我留言。

言归正传,从这个继承关系图中,我们可以发现公平锁和非公平锁是继承了Sync这个抽象类,而这个Sync也继承了一个AbstrackQueuedSynchronizer抽象类,从这个类名我们可以知道这是一个抽象出来的队列,它里边的acquire方法是实现公平锁和非公平锁的关键,这个方法里调用了非公平锁和公平锁的实现tryAcquire方法。

构造方法

深入了解ReentrantLock可重入锁_第2张图片

从上图中我们可以发现,ReentranLock为我们提供了两个构造方法,一个有参一个无参,从源码的方法名我们可以知道,无参默认为我们提供的是非公平锁的实现,有参是根据传入的boolean值进行判断返回公平锁或者给公平锁。

非公平锁

我们先来看非公平锁的实现:
深入了解ReentrantLock可重入锁_第3张图片

从上面源码中我们可以看到非公平锁的实现非常简单,根据状态值判断,如果状态值显示为空闲,那么就通过cas从多个线程中竞争选择一个,把选中的这个线程设置为最高级,等它执行完再周而复始继续设置,知道所有的线程都执行完成。

公平锁

公平锁的源码:
深入了解ReentrantLock可重入锁_第4张图片

公平锁和非公平锁的实现大部分相同,但是我们从源码中看到还是有一些不同的,那就是这个hasQueuePredecessors方法,公平锁除了判断当前状态之外还要判断一下AbstrackQueuedSynchronizer(这个类名太长了后边我们简称为AQS)里的hasQueuedPredecessors方法,从类名和方法名上我们可以知道AQS其实就是一个队列,队列的特性就是first In first out(FIFO)先进先出,根据这个特性判断队列里是否有比当前线程更早进来的线程,如果有那么就继续等待,没有那么就将当前线程设为最高优先级,从而实现了我先来我先处理的公平规则。

你可能感兴趣的:(java多线程)