- 创建锁对象
因为ReentrantLock默认非公平锁,这里不做考虑,直接构建有参公平锁
public ReentrantLock(boolean fair) {
this.sync = (ReentrantLock.Sync)(fair ? new ReentrantLock.FairSync() : new ReentrantLock.NonfairSync());
}
根据入参fair我们可以看到锁同步对象为ReentrantLock.FairSync()
static final class FairSync extends ReentrantLock.Sync {
private static final long serialVersionUID = -3000897897090466540L;
FairSync() {
}
@ReservedStackAccess
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = this.getState();
if (c == 0) {
if (!this.hasQueuedPredecessors() && this.compareAndSetState(0, acquires)) {
this.setExclusiveOwnerThread(current);
return true;
}
} else if (current == this.getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) {
throw new Error("Maximum lock count exceeded");
}
this.setState(nextc);
return true;
}
return false;
}
}
公平同步锁继承Sync,且里面只有一个方法
- 获取锁tryAcquire
protected final boolean tryAcquire(int acquires) {
//获取当前线程
Thread current = Thread.currentThread();
// 获取该锁当前状态
int c = this.getState();
// 状态为0,可以获取锁
if (c == 0) {
// !this.hasQueuedPredecessors() 成立,cas状态0->1 ======》当前线程获取锁
if (!this.hasQueuedPredecessors() && this.compareAndSetState(0, acquires)) {
this.setExclusiveOwnerThread(current);
return true;
}
} else if (current == this.getExclusiveOwnerThread()) {
//当前线程与获取锁线程相同,重入且状态计数值+1
int nextc = c + acquires;
if (nextc < 0) {
throw new Error("Maximum lock count exceeded");
}
this.setState(nextc);
return true;
}
return false;
}
- !this.hasQueuedPredecessors() 延申
相关代码如下:
public final boolean hasQueuedPredecessors() {
AbstractQueuedSynchronizer.Node h;
//判断队列头是否为null
if ((h = this.head) != null) {
//头不为null,创建临时节点s
AbstractQueuedSynchronizer.Node s;
if ((s = h.next) == null || s.waitStatus > 0) {
//赋值h.next给s,如果赋值后s为空,或者waitStatus 大于0,重置s
s = null;
//复制链表队尾给临时节点p ,当p不等于队首,且不等于null时,p不断置换为p上一节点,循环
for(AbstractQueuedSynchronizer.Node p = this.tail; p != h && p != null; p = p.prev) {
//临时节点p等待状态小于等于0时,复制p给s
if (p.waitStatus <= 0) {
s = p;
}
}
}
//s不为null且不属于当前线程,返回true
if (s != null && s.thread != Thread.currentThread()) {
return true;
}
}
return false;
}
方法中维护了3个临时节点,h、s、p
条件1:
h=当前队首,判断队首为null,说明排队队列没有线程,直接跳出代码返回false (!this.hasQueuedPredecessors()为true直接获取锁)
条件2:
队首不为null,当node.next为空,或者等待状态大于0,重置s为null,赋值p为队尾,根据条件p不等于null且p不等于队首,队尾向前迭代------->迭代过程中找到node等待状态小于等于0,赋值给s,进入下级判断,s!=null,返回true (!this.hasQueuedPredecessors()为false取锁失败)