前言
前面用了 4 篇文章为本文分析 ReentrantLock
源码做了一些铺垫,
ReentrantLock 源码分析 - AbstractQueuedSynchronizer 详解(一)
ReentrantLock 源码分析 - AbstractQueuedSynchronizer 详解(二)
赶紧趁热打铁,来看下 ReentrantLock
非公平锁的lock()
方法是如何实现的。
正文
知识回顾
ReentrantLock
既可以实现非公平锁,也可以实现公平锁。
通过 ReentrantLock lock = ReentrantLock(false)
的方式可以创建一个非公平锁。
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
从上面的构造方法可以看出, 当传入 false
时,new 了个 NonfairSync
对象。
NonfairSync 类
通过查看源码,可以看出NonfairSync
继承 Sync
。
那 Sync
又是什么? 请往后看。
static final class NonfairSync extends Sync {
}
Sync 类
Sync
继承自我们熟悉的 AQS
, 前面花了很多篇幅去介绍 本文会涉及 到的 AQS
部分实现。Sync
中有一个nonfairTryAcquire(int acquire)
方法,该方法在前面的文章中也举例说明过,
我们先跳过这段源码分析,接着往下看 :
abstract static class Sync extends AbstractQueuedSynchronizer {
// 知识回顾:前面有介绍 ReentrantLock 是可重入锁,state 表示重入次数
final boolean nonfairTryAcquire(int acquires) {
// 获取当前线程
final Thread current = Thread.currentThread();
// 获取 state
int c = getState();
// 如果 state == 0,表示锁未被占用,
// 然后通过 CAS 操作,把 state + 1,标记锁被占用
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
// 如果锁被线程 A 占用
// 判断当前线程是否就是线程 A
// 如果是,就把 state +1
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;
}
}
lock() 方法
回归初心,来看下 lock 的调用方式
ReentrantLock lock = new ReentrantLock(false);
lock.lock();
而 lock() 的实现如下:
public void lock() {
sync.lock();
}
根据前面讲的,此时 sync = NonfairSync()
,
而 NonfairSync
的 lock
方法实现如下:
final void lock() {
// 通过 CAS 原子操作,把 state 由 0 设置为 1
if (compareAndSetState(0, 1))
// 设置成功,把当前线程标记为独占锁持有者
setExclusiveOwnerThread(Thread.currentThread());
else
// 如果 cas 失败,表示抢占锁失败,把当前线程放入 AQS 队列,入队后,还会有一系列操作
// AQS 的 acquire(int arg) 方法, 上文有详细讲过
acquire(1);
}
tryAcquire(int arg) 方法
前面提到了 AQS 的 acquire
方法中调用了 tryAcquire
方法,该方法主要目的是获取锁资源, 它本身在 AQS 中是抽象方法,由具体的子类实现的(在此处就是 NonfairSync
), 而 tryAcquire
方法又调用了nonfairTryAcquire
方法, 这时候我们就可以 传送
到 Sync 类 介绍部分,去阅读那段nonfairTryAcquire
方法的源码
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
总结
可以看出本文内容非常少,我们前期花了大量的功夫去挖掘一些基础知识,因为 ReentrantLock
本身就是基于 AQS 实现的,而 AQS 又依赖于下面的小知识
因此把前面的基础打好,ReentrantLock
的具体实现就很容易看懂了。
再次总结下本文主要内容:
- ReentrantLock 可以通过
new ReentrantLock(false)
方式实现非公平锁 - 第 1 步 产生的结果就是 new 了一个
NonfairSync
- 而
NonfairSync
本文继承自Sync
, 而Sync
又继承自 AQS - 当调用非公平锁的
lock()
方法时,就是调用NonfairSync
的lock
方法 - 第 4 步就是一个抢占锁的过程
- 抢占成功与否是根据 CAS 操作结果判定的
- 抢占失败的线程会调用
acquire
方法,继续尝试获取锁,获取失败就会被被放入AQS
队列(具体策略看上一篇文章)
来源:oschina
链接:https://my.oschina.net/u/3984985/blog/4255617