JDK类库源码分析系列2-AbstractQueuedSynchronizer-ReentrantLock
Posted _微风轻起
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK类库源码分析系列2-AbstractQueuedSynchronizer-ReentrantLock相关的知识,希望对你有一定的参考价值。
上一篇我们梳理了`AbstractQueuedSynchronizer`(`AQS`)的一些方法,这一篇我们就来看其的子类实现`ReentrantLcok`可重入锁。
一、结构
1、继承关系
public class ReentrantLock implements Lock, java.io.Serializable {
可以看到其是实现接口Lock
。
2、Lock
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
这个就是锁的接口方法。
1)、lock():方法就是获取锁。
2)、void lockInterruptibly() throws InterruptedException:以可中断的方法获取锁,与lock()方法比较,就是可抛出InterruptedException
异常。
3)、tryLock():尝试获取锁。
4)、boolean tryLock(long time, TimeUnit unit) throws InterruptedException:这个也就是会抛出InterruptedException
。
5)、unlock():释放锁。
6)、newCondition():获取该锁对应的Condition
。
二、变量
1、sync
/** Synchronizer providing all implementation mechanics */
private final Sync sync;
其全局变量就这个Sync
同步对象,其一般是实现的AQS
。
三、Sync子类
1、结构
abstract static class Sync extends AbstractQueuedSynchronizer {
可以看到其是一个静态的内部抽象类,然后继承的AQS
。
2、方法
1)、nonfairTryAcquire(int acquires)
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
这个方法就是以非公平的方式尝试去获取锁。
其首先是判断getState()
,如果为0.就表示当前还没有其他的占用锁,就尝试通过compareAndSetState(0, acquires)
来设置status
,如果成功了就表示获取锁成功了,就调用setExclusiveOwnerThread(current)
将独占的线程设置为当前线程,如果不成功就返回false
。
我们再来看如果getState()
不为0,即表示被占用了,就判断当前线程是不是独占线程,是的话,就c + acquires
累加重置status
的值。不然也是到最后返回false
。
2)、tryRelease(int releases)
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
这个是释放锁,也就是跟前面上锁一样,判断status
的状态。
3)、isHeldExclusively()
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
判断占有线程是不是当前线程。
4)、newCondition()
final ConditionObject newCondition() {
return new ConditionObject();
}
创建ConditionObject
对象(Condition
)。
5)、getOwner()
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
获取拥有锁的线程。
6)、getHoldCount()
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
获取status
的值,也就是还有多少status
值没有释放,可以看到这里还调用了isHeldExclusively()
,就是说,如果不是拥有线程的话就返回0
。
7)、isLocked()
final boolean isLocked() {
return getState() != 0;
}
判断当前状态是不是被锁住的。
四、NonfairSync子类
NonfairSync
这个类就是获取锁的非公平实现。
1、结构
static final class NonfairSync extends Sync {
其继承的Sync
类。
2、方法
1)、tryAcquire(int acquires)
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
尝试获取锁,其直接调用的nonfairTryAcquire(acquires)
。
五、FairSync子类
1、结构
static final class FairSync extends Sync {
这个也是继承的Sync
,不过这个是以公平的方式尝试获取锁。
2、方法
1)、tryAcquire(int acquires)
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
这个方法与前面的非公平方式获取锁的不同是其主要多了一个方法的判断hasQueuedPredecessors()
,这个方法我们在前一篇文章有过梳理,其主要就是判断head
节点的后继节点是不是当前节点,如果不是
就返回true
,而我们这里是!hasQueuedPredecessors()
。所以这里就是如果head
节点的后继节点是当前线程的话,就为true
,然后就去争取锁了,所以借由这个hasQueuedPredecessors()
,就实现了链式的一个一个按顺序争取锁的处理。
六、方法
1、ReentrantLock()
public ReentrantLock() {
sync = new NonfairSync();
}
如果构造方法没有入参,我们默认Sync
就是NonfairSync
非公平实现。
2、ReentrantLock(boolean fair)
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
这个有入参的就是按照入参来决定看是使用公平方法还是非公平。
3、lock()
public void lock() {
sync.acquire(1);
}
获取锁,正如我们在前一篇文章提到的,入参默认为1
,就是将status
设置为1。
4、lockInterruptibly()
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
以可抛出异常InterruptedException
的方式去获取锁。
5、tryLock()
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
6、tryLock()
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
初始获取锁,可以看到其是调用的nonfairTryAcquire
即非公平方式获取锁。
public abstract class AbstractQueuedSynchronizer
.........
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
7、tryLock(long timeout, TimeUnit unit)
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
这个就是以有时间限制的方法去尝试获取锁。
8、unlock()
public void unlock() {
sync.release(1);
}
释放锁。
public abstract class AbstractQueuedSynchronizer
.............
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
9、newCondition()
public Condition newCondition() {
return sync.newCondition();
}
创建对应的Condition
。
10、getHoldCount()
public int getHoldCount() {
return sync.getHoldCount();
}
即status
的值。
11、isHeldByCurrentThread()
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
判断锁是不是被当前线程持有。
12、isLocked()
final boolean isLocked() {
return getState() != 0;
}
当前AQS
是否有被线程占有。
13、isFair()
public final boolean isFair() {
return sync instanceof FairSync;
}
判断当前Sync
是那种实现。
14、hasQueuedThread(Thread thread)
public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
判断等待节点中,有没由节点的线程是入参thread
。
以上是关于JDK类库源码分析系列2-AbstractQueuedSynchronizer-ReentrantLock的主要内容,如果未能解决你的问题,请参考以下文章
JDK类库源码分析系列2-AbstractQueuedSynchronizer-CountDownLatch
JDK类库源码分析系列2-AbstractQueuedSynchronizer-ReentrantReadWriteLock