ReentrantLock和Synchronized关键字具有相同的基本行为和语义,但是,ReentrantLock具备更好的可扩展性。
ReentrantLock实现了Lock接口:
public class ReentrantLock implements Lock, java.io.Serializable
底层操作其实是基于AQS(AbstractQueuedSynchronizer)实现的,ReentrantLock内部封装了一个继承AQS的静态抽象类Sync
abstract static class Sync extends AbstractQueuedSynchronizer
ReentrantLock的公平锁实现、非公平锁实现分别是FairSync、NonfairSync,二者继承自Sync。所以,可以看出,ReentrantLock是基于AQS实现的。
static final class FairSync extends Sync
static final class NonfairSync extends Sync
ReentrantLock默认的情况下是采用的非公平锁,从下面的构造函数可以看出来:
public ReentrantLock() {
sync = new NonfairSync();
}
下面,我们来看看公平锁FairSync和非公平锁NonfairSync的lock操作,因为从lock操作可以看出FairSync和NonfairSync的区别。
公平锁FairSync的lock()操作如下:
final void lock() {
acquire(1);
}
// AQS中的
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 公平锁的模式下,会先去看看CLH队列中有没有等待执行的线程,如果没有,当前线程才尝试通过CAS机制去获取锁
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;
}
非公平锁NonfairSync的lock()操作如下:
final void lock() {
// 直接通过CAS机制去获取锁,获取失败,才调用acquire(1)方法。给了当前线程一个同CLH队列中的线程抢夺锁的机会,如果线程在CLH队列中了,就只能是公平获取
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
// AQS类中的
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
ReentrantLock对象的lock方法如下:
// sync通过创建ReentrantLock时指定是公平锁还是非公平锁
public void lock() {
sync.lock();
}