ReentrantLock内部有一个继承于AQS的Sync类,正如AQS源码里所说的:AQS的子类们应该被定义为非公开的内部辅助类,并且被用来实现它们外部类的其它内部类的同步属性,即ReentrantLock一样,一个Sync内部类实现了AQS的一些同步方法,并且内部公平和非公平锁类调用了这一些方法来进行锁操作。
AQS还为ReentrantLock提供了一个原子值state来表示状态,ReentrantLock定义了改变这个状态值的get和set方法,并且定义这个状态值的意义,用来获取或释放对象。
我们一般都是这样使用ReentrantLock:
1、private final Lock lock = new ReentrantLock()
2、private final Lock lock = new ReentrantLock(Boolean fair)
3、lock.lock()
4、lock.unlock()
构造方法:
首先,第一种方法调用了ReentrantLock的无参构造器,默认创建了一个NonfairSync对象,代码如下:
public ReentrantLock() {
sync = new NonfairSync();
}
第二种会按照传的参数来构造公平或非公平锁的对象
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
调用lock方法:
首先看内部类NonfairSync:
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
1、首先会直接判断State值,若为0,则将其置为1,并且将当前线程置为独享模式的持有者,并取得资源
2、否则会调用AQS中的acquire方法,然后acquire方法会调用NonfairSync中重写的tryAcquire方法来进行尝试获锁的判断
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
/*首先调用AQS的getState方法来获取state状态,值默认初始为0*/
int c = getState();
/*为0,证明没有线程持有锁,利用原子操作将state+1,并将当前线程设为当前独享模式的持有者,然后返回true*/
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
3、若锁已被当前线程所占有,即状态值不为0,则将当前状态值设置为:当前状态值加上acquires参数(默认为1)。然后返回true,证明再次获锁成功。这块代码为可重入的体现
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
/*设置状态值为修改后的值*/
setState(nextc);
/*成功获锁*/
return true;
}
内部类FairSync:
final void lock() {
acquire(1);
}
这里是直接调用AQS中的acquire方法,然后acquire方法会调用FairSync中重写的tryAcquire方法来进行尝试获锁的判断
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
/*获取state值*/
int c = getState();
/*公平的体现。若state为0*/
if (c == 0) {
当前节点为等待队列头节点并且能将state设置为acquires代表的值,则成功。这块代码与非公平锁不同的地方就在这,判断当前节点是否为头节点的操作,也是公平的体现,即每次只有队列中的第一个节点才能获取资源
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
若锁已被当前线程所占有,即状态值不为0,则将当前状态值设置为:当前状态值加上acquires参数(默认为1)。然后返回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;
}
}
判断当前节点是否是队列中的第一个节点,是就返回false,不是则返回true
public final boolean hasQueuedPredecessors() {
/* 1、若当前队列为空,则h==t,返回false
2、若当前队列只有一个节点,则返回false
3、否则若当前线程所属节点不为第二个节点,返回true;若等于,返回false*/
Node t = tail;
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
unlock的调用:
public void unlock() {
sync.release(1);
}
它会调用AQS的release方法,然后release方法调用Sync重写的tryRelease方法来释放资源
protected final boolean tryRelease(int releases) {
/*将当前状态值减去releases(默认1)*/
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
/*标志位,若c=0,则返回true,不为0.返回false*/
boolean free = false;
/*若修改后的状态值为0,则证明可以释放,并将持有当前独享模式的线程置空*/
if (c == 0) {
/*设置标志位为0*/
free = true;
setExclusiveOwnerThread(null);
}
/*设置修改后的状态值*/
setState(c);
/*若free返回true*/
return free;
}