什么是ReentrantLock
ReentrantLock是一个可重入的互斥锁锁, 实现Lock接口。具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义。ReentrantLock是显示的获取或释放锁,并且有锁超时,锁中断等功能。
内部维户了一个Sync的内部类,继承AQS队列同步器。
ReentrantLock 将由最近成功获得锁,并且还没有释放该锁的线程所拥有。当锁没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法来检查此情况是否发生。
默认是非公平锁的实现方式
非公平锁获取和释放流程
加锁
执行
lock方法加锁时调用内部NonfairSync的lock方法,第一次会快速尝试获取锁,执行AQS类的compareAndSetState方法(CAS)更改同步状态成员变量state,如果获取成功 则设置当前线程为锁的持有者。失败则执行AQS类的acquire方法,acquire会调用的AQS中的tryAcquire方法。这个tryAcquire方法需要自定义同步组件提供实现。tryAcquire的具体流程是执行Sync类的nonfairTryAcquire方法:首先记录当前加锁线程,然后调用getState获取同步状态,如果为0时 说明锁处于空闲状态,可以获取,会以CAS方式修改state变量。成功则设置当前线程 返回true。否则执行重入判断,判断当前访问线程和已经持有锁的线程是否是同一个。如果相同,将同步状态值进行增加,并返回true。否则返回加锁失败false解锁
- 解锁
unlock方法会调用内部类Sync的tryRelease方法。tryRelease首先调用getState方法获取同步状态,并进行了减法操作。在判断释放操作是不是当前线程,不是则抛出异常,然后判断同步状态是否等于0,如果是0,说明没有线程持有,锁是空闲的,则将当前锁的持有者设置为null, 方便其它线程获取,并返回true。否则返回false
- 解锁
ReentrantLock常用方法介绍
getHoldCount()查询当前线程保持此锁的次数。getOwner()返回目前拥有此锁的线程getQueueLength()返回正等待获取此锁的线程估计数getWaitingThreads(Condition condition)返回一个 collection,它包含可能正在等待与此锁相关给定条件的那些线程。boolean hasQueuedThread(Thread thread)查询给定线程是否正在等待获取此锁。boolean hasQueuedThreads()查询是否有些线程正在等待获取此锁。boolean hasWaiters(Condition condition)查询是否有些线程正在等待与此锁有关的给定条件boolean isHeldByCurrentThread()查询当前线程是否保持此锁。void lock()获取锁。void lockInterruptibly()如果当前线程未被中断,则获取锁。Condition newCondition()返回用来与此 Lock 实例一起使用的 Condition 实例。boolean tryLock()仅在调用时锁未被另一个线程保持的情况下,才获取该锁。void unlock()释放锁
程序中使用
1 | private ReentrantLock lock=new ReentrantLock(); |
ReentrantLock源码分析
1 | package java.util.concurrent.locks; |
