ReentrantLock源码
1. 源码注释
-
跟synchronized具有相同的功能和语义(都是互斥锁),但它具有更好的拓展性。
-
通过这两个方法判断当前线程是否拥有锁
isHeldByCurrentThread
getHoldCount
-
构造方法支持使用参数来让锁设计为公平锁,公平锁一般的吞吐量会低一些,但一定程度保住了“相对公平”
-
不计时 tryLock()方法不符合公平锁的设定
-
在try代码块之前调用lock,这是最应该使用的方式
-
Lock接口还定义了一些监听锁状态的方法
-
一个被序列化的锁是处于不锁定状态的
2. 分析
2.1 内部类
ReentrantLock有三个内部类
- 继承了AQS的Sync
- Sync的子类NonfairSync
- Sync的子类FairSync。
通过子类可以看到,ReentrantLock是支持公平锁和非公平锁的
2.2 构造方法
//无参构造方法,默认使用非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
//通过制定参数,可以初始化公平锁或非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
2.3 Lock方法
-
公平锁
public void lock() { sync.lock(); } //FairSync中的lock方法 final void lock() { acquire(1); } //AQS中的方法 public final void acquire(int arg) { //尝试获取锁,成功则返回true,则当前方法结束 if (!tryAcquire(arg) && //当前锁被其他线程持有,准备入等待队列 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } //FairSync中的方法,尝试获取锁 protected final boolean tryAcquire(int acquires) { //获取当前线程 final Thread current = Thread.currentThread(); //获取锁状态 int c = getState(); //C == 0,则当前无锁 if (c == 0) { //队列未初始化,hasQP方法返回false if (!hasQueuedPredecessors() && //将state值设为1 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; } //AQS中的判断方法 //无锁时,当前队列中没有元素,则返回false //有锁时,当前队列 public final boolean hasQueuedPredecessors() { Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); } //创建等待队列中的结点 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(node); return node; } 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:刚插入队列的新节点 //arg: 1 final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { //获取新节点的前一个节点 final Node p = node.predecessor(); //如果前一个节点为头结点,尝试获取锁 if (p == head && tryAcquire(arg)) { //获取成功,则将当前节点设为头结点 setHead(node); p.next = null; // help GC failed = false; return interrupted; } //获取锁失败,或者当前节点不是队列中有机会获取锁的结点 //判断当前节点是否应该被park //true则将当前节点park if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { //当插入尝试时,成功获取锁,则将队列中的结点设置为取消状态 if (failed) cancelAcquire(node); } } //取消获取锁的状态 private void cancelAcquire(Node node) { // Ignore if node doesn't exist if (node == null) return; node.thread = null; Node pred = node.prev; while (pred.waitStatus > 0) node.prev = pred = pred.prev; Node predNext = pred.next; //当前节点的状态设置为取消 node.waitStatus = Node.CANCELLED; //如果当前节点为队尾,就把空节点放到队尾,且将它头尾相连 if (node == tail && compareAndSetTail(node, pred)) { compareAndSetNext(pred, predNext, null); } else { int ws; if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) && pred.thread != null) { Node next = node.next; if (next != null && next.waitStatus <= 0) compareAndSetNext(pred, predNext, next); } else { unparkSuccessor(node); } node.next = node; // help GC } }
-
非公平锁
//非公平锁的lock方法 final void lock() { //一进来先进行CAS抢占锁 if (compareAndSetState(0, 1)) //抢占成功则设置当前线程为锁的持有线程 setExclusiveOwnerThread(Thread.currentThread()); else //失败则尝试获取锁 acquire(1); } public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { //非公平锁的特别之处,在请求锁时,当锁可以被获取时,直接进行CAS抢占。 //抢占失败,则进行正常排队流程,不再抢占 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; }
2.4 unlock方法
public void unlock() {
sync.release(1);
}
//
//arg:1
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
//
//releases:1
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
//如果当前解锁线程不等于正在持有锁的线程,则抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//如果释放后处于无锁状态,则将当前锁持有者设为空
//如果释放后不等于0,当前存在重入,则将重入锁状态-1,
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
//唤醒后继节点
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
//将节点status设为0,代表当前节点正在持有锁
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
if (s == null || s.waitStatus > 0) {
//如果后续节点为空,或者status为cancel,设置该节点为null
s = null;
//从尾部遍历,寻找临近s的等待状态有效的节点
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
//如果后继节点有效
if (s != null)
//唤醒该线程
LockSupport.unpark(s.thread);
}