地狱空荡荡,魔鬼在人间
ReentrantLock底层中有六个类,这六个类实现了ReentrantLock所有特性。
- Sync:继承AQS。
- AQS:队列同步器。
- Node:同步队列管理员,双向链表,管理获取锁这个过程。
- ConditionObject:等待队列管理员。
- NonfairSync:非公平锁,继承Sync。
- FairSync:公平锁,继承Sync。
ReentrantLock一共有两个队列。
- 同步队列:当线程尝试获取锁而等待加入同步队列。thread.lock()进入的就是等待队列。
- 等待队列:等待队列是第二梯队,获取锁轮不到它,它需要首先调用signal()进入同步队列,才能准备获取锁。那么如何进入等待队列呢,调用await()释放锁,进入等待队列,等待队列有多个。
ReentrantLock中通过state状态位判断是否可以获取锁。
- 为1:锁已经被别人取走。
- 为0:可以尝试获取锁。
ReentrantLock
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Collection;
public class ReentrantLock implements Lock, java.io.Serializable {
//首先,就是我们最经常使用的构造方法,默认使用的都是非公平锁。
//NofairSync,就是不公平锁的意思。
public ReentrantLock() {
sync = new NonfairSync();
}
//这里,你也可以构造一个公平锁出来,传递true参数即可。
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
//下边这么长,是一个内部类Sync。
//我们的公平锁,非公平锁都是集成Sync,自然里边的方法都可以用。
//很长,不用看,看下边的公平锁和非公平锁就可以。
abstract static class Sync extends AbstractQueuedSynchronizer {
//非公平锁就是这个,非公平锁类里判断能不能获取锁就是通过这个方法搞的。
//将非公平锁的这个方法,与公平锁的这个方法一对比,其意自现。
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
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;
}
}
//非公平锁
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
这里可以看到这个方法compareAndSetState()
比较并改变状态,简称CAS,这个和CAS思想是一样的。
看看state是不是0,是0的话就修改状态为1.
并获取锁,设置锁线程为当前自己线程。**/
//非公平锁的lock方法
//如果执行成功,则获取锁,失败,则执行acquire(1)方法。
//acquire()方法在AbstractQueuedSynchronizer内部。
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
//这里非公平锁调用了父类Sync里的方法,判断是否可以进入获取锁。
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
//公平锁
static final class FairSync extends Sync {
//上锁,修改状态state为1。
final void lock() {
acquire(1);
}
//在多线程竞争锁的时候,谁能获取小红的欢心,获取锁就是这个方法。
//首先判断一下状态位State为0还是为1.
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//为0,则尝试获取锁。
if (c == 0) {
//非公平锁那里的判断是两个
//公平锁这里的判断是三个判断
//相比非公平锁,这里多了一个判断,判断一下自己本线程是否在等待队列的首部。
//另外两个操作一样,都是CAS操作以及获取锁操作。
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//为1,判断是不是自己本线程,是自己就计数器++
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
//非0非1,返回false。
return false;
}
}
//这里是ReentrantLock的方法,可以看到它使用的是内部类Sync的方法。
//所以使用ReentrantLock时,下边很多方法都是Sync的,其实就是使用的Sync。
//默认使用的都是非公平锁的lock()方法。
public void lock() {
sync.lock();
}
//统一都是Sync的方法。
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
//释放锁,执行release方法。
//release方法是抽象类AQS中的方法,在下边。
public void unlock() {
sync.release(1);
}
//这里我删掉了非常多的方法,功能很多,不是重要API。
//统一都是Sync的方法,看似你使用的是ReentrantLock但是实际上内部已经被Sync腐蚀了。
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}
public String toString() {
Thread o = sync.getOwner();
return super.toString() + ((o == null) ?
"[Unlocked]" :
"[Locked by thread " + o.getName() + "]");
}
}
AbstractQueuedSynchronizer
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import sun.misc.Unsafe;
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
private static final long serialVersionUID = 7373984972572414691L;
protected AbstractQueuedSynchronizer() { }
//内部类Node。
static final class Node {
Node() {
}
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
//这个方法是非公平锁类中,执行lock(),执行CAS操作后,为false
//参考上边。
//在这里调用tryAcquire再次尝试,如果失败则挂起,进入同步队列等待。
//tryAcquire是ReentranLock中获取锁的方法,去上边看。
//addWaiter()方法是这个类里的,在上边。
//acquireQueueed
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
//当线程执行unlock()方法时,就会执行AQS中的release方法。
//根据tryRelease()方法返回boolean。
//tryRlease()方法是ReentrantLock中的释放锁的方法。
//AQS中没有具体业务实现,由子类进行自定义。
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
//尝试将打包好的Node类,加入同步队列
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//获取上一个节点
final Node p = node.predecessor();
//判断node是否是头节点,并尝试获取锁。
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null;
failed = false;
return interrupted;
}
//shouldParkAfterFailedAcquire:返回当前线程是否需要挂起。
//parkAndCheckInterrupt():执行挂起操作。
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//这个方法用于返回一个Node.
//将当前线程改为Node类,加入同步队列进行等待。
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
//判断队列里有没有线程,判断尾部节点有没有线程
//有线程就加入尾部。
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//没有线程,需要初始化同步队列执行enq方法。
enq(node);
return node;
}
//自旋及CAS写入队列
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) {
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
//将当前node设置为头节点。
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
//线程是否在队列中等待。
public final boolean isQueued(Thread thread) {
if (thread == null)
throw new NullPointerException();
for (Node p = tail; p != null; p = p.prev)
if (p.thread == thread)
return true;
return false;
}
//公平锁中,在尝试获取锁操作时,使用这个方法判断是否在队列的头部。
public final boolean hasQueuedPredecessors() {
Node t = tail;
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
//队列长度。
public final int getQueueLength() {
int n = 0;
for (Node p = tail; p != null; p = p.prev) {
if (p.thread != null)
++n;
}
return n;
}
//队列中有哪些线程。
public final Collection<Thread> getQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
return list;
}
//等待队列长度。
public final int getWaitQueueLength(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitQueueLength();
}
//等待队列中有哪些线程。
public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitingThreads();
}
}