什么是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; |