自由一定是相对的,只有自律的人,才能有自由。
首先看ReetrantLock的构造方法
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
基于传入的boolean变量决定创建公平锁or非公平锁,sync是ReetrantLock的成员变量,并发包下的很多类都是以这种方式,存在一个成员变量sync,并有一个内部类sync继承自AQS(AbstractQueuedSynchronizer)抽象队列同步器
先看公平锁FairSync,调用lock方法
java.util.concurrent.locks.ReentrantLock#lock
java.util.concurrent.locks.ReentrantLock.FairSync#lock
final void lock() {
acquire(1);
}
java.util.concurrent.locks.AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
// 尝试获取锁,如果获取失败,尝试以独占类型加到队列中
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
java.util.concurrent.locks.ReentrantLock.FairSync#tryAcquire
protected final boolean tryAcquire(int acquires) {
// 拿到当前线程
final Thread current = Thread.currentThread();
// 获取state
int c = getState();
// 如果为0,表示没有任何人获取锁,可以进行加锁
if (c == 0) {
// 如果等待队列中没有等待的线程(表明上个拿到锁的线程刚执行完,并且有其他线程正在等待获取锁)并且使用cas设置状态成功(成功获取到锁)
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
// 设置独占线程为当前线程
setExclusiveOwnerThread(current);
return true;
}
}
// 如果当前线程是锁的独占线程,state加本次获取次数并返回获取成功
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
java.util.concurrent.locks.AbstractQueuedSynchronizer#addWaiter
// 入队列
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
// 如果队列的尾节点不为空,则将入队节点的前驱节点指向之前的尾节点,并通过cas设置尾节点为新入队的节点,设置成功后,将之前的尾节点的下个节点设置为新入队的节点
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
// 如果不满足,执行入队方法
enq(node);
return node;
}
java.util.concurrent.locks.AbstractQueuedSynchronizer#enq
// 入队
private Node enq(final Node node) {
// 死循环多次尝试
for (;;) {
Node t = tail;
if (t == null) { // 如果tail为空(队列的初始状态)
// 通过cas创建初始节点,设置成功后将尾节点也指向头结点
if (compareAndSetHead(new Node()))
tail = head;
} else { // 如果尾节点不为空,设置新节点的前驱节点为尾节点,并通过cas设置尾节点为新入队的节点,设置成功后,将之前的尾节点的下个节点设置为新入队的节点
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
我们来看下非公平锁的lock方法
java.util.concurrent.locks.ReentrantLock.NonfairSync#lock
final void lock() {
// 可以看出跟公平锁的区别就是,非公平锁的lock会一上来就尝试获取锁,如果获取成功,设置独占线程为当前线程,即非公平锁可以插队
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}