ReetranLock 源码解析
程序员文章站
2022-06-20 20:29:30
...
ReetranLock 类
1. 方法含义
方法 | 说明 |
---|---|
lock() | 阻塞的获得锁 |
tryLock() | 非阻塞式获取锁 |
unlock() | 释放锁 |
newCondition() | |
tryLock(long timeout, TimeUnit unit) |
2. 方法解析
public void lock() {
// 直接调用同步器的lock()
sync.lock();
}
/**
* 非阻塞式获取锁
*/
public boolean tryLock() {
// 直接调用非公平锁的获锁方法
return sync.nonfairTryAcquire(1);
}
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
1. 队列同步器
1.1 队列同步器中的锁操作
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
// 阻塞式获取锁
public final void acquire(int arg) {
/*
1. 尝试非阻塞是获取锁,
2. 获取锁失败,addWaiter(Node.EXCLUSIVE),将线程添加到等待队列
3. 添加成功,自旋于 acquireQueued()
*/
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// 自旋,直到获取到锁
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);
// 去点前一个结点的next引用
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
// 如果faile等于true,当前节点取消等待
if (failed)
cancelAcquire(node);
}
}
}
1.2 队列同步器中的等待队列操作
// 添加等待线程
private Node addWaiter(Node mode) {
// 创建节点
Node node = new Node(Thread.currentThread(), mode);
// 获取等待队列尾节点
Node pred = tail;
// 尾节点不为空,即等待队列不为空
if (pred != null) {
node.prev = pred;
// 使用 CAS 重置尾节点
if (compareAndSetTail(pred, node)) {
// 重置成功,将尾节点的next指针指向本节点
pred.next = node;
return node;
}
}
// 若尾节点为空或CAS失败
enq(node);
return node;
}
// 插入线程到等待队列,自旋直到插入成功
private Node enq(final Node node) {
// 无限循环知道 cas 成功
for (;;) {
Node t = tail;
if (t == null) {
// CAS 设置头节点
if (compareAndSetHead(new Node()))
// 头节点设置成功则设置尾节点
tail = head;
} else { // 等待队列不为空
node.prev = t;
// CAS 设置尾节点
if (compareAndSetTail(t, node)) {
// CAS 成功则将前尾节点的next指向当前节点
t.next = node;
return t;
}
}
}
}
1.3 节点取消等待
private void cancelAcquire(Node node) {
if (node == null)
return;
// 将当前节点绑定的线程设置为空
node.thread = null;
// 获取前节点
Node pred = node.prev;
// 如果前节点的等待状态大于 0 ,不断踢出队列
while (pred.waitStatus > 0)
// pred = pred.prev
// node.prev = pred
node.prev = pred = pred.prev;
Node predNext = pred.next;
// 设置当前节点的等待状态,将当前节点设置为取消等待状态
node.waitStatus = Node.CANCELLED;
// 如果当前节点是尾节点,CAS设置尾节点为前节点
if (node == tail && compareAndSetTail(node, pred)) {
// 将前节点的next节点设置为空
compareAndSetNext(pred, predNext, null);
} else {
int ws;
/*
判断条件
1. 前节点不是头节点
2. 前节点的状态是SIGNAL或者状态值小于0且将其CAS设置为SIGNAL状态成功
3. 前节点绑定的线程不为空
*/
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
// 获取当前节点的next节点
Node next = node.next;
// 如果next不为空且不是处于取消等待状态
if (next != null && next.waitStatus <= 0)
// 将前节点的next节点设置为next
compareAndSetNext(pred, predNext, next);
} else {
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
// 如果等待状态小于 0, 将其等待状态设置为 0 (初始化状态)
compareAndSetWaitStatus(node, ws, 0);
// 查看其next节点
Node s = node.next;
// 如果s为空或者为取消等待状态
if (s == null || s.waitStatus > 0) {
s = null;
//
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
2. sync 内部类
ReentrantLock 内部维护了一个队列同步器继承于 AbstractQueuedSynchronizer ,lock的操作都是基于队列同步器进行的
1.Sync类实现
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
// 抽象声明lock方法,具体由实现类(公平锁和非公平锁实现)
abstract void lock();
// 非公平锁的非阻塞获取锁的具体实现
final boolean nonfairTryAcquire(int acquires) {
// 获取当前线程
final Thread current = Thread.currentThread();
// 获取同步状态
int c = getState();
if (c == 0) {
// 如果同步状态为 0
// 使用CAS更新同步状态为 1
if (compareAndSetState(0, acquires)) {
// 将当前线程设置为获得锁的线程
setExclusiveOwnerThread(current);
return true;
}
}
// 如果同步状态不为0
// 且或得所得线程为当前线程
else if (current == getExclusiveOwnerThread()) {
// 同步状态+1
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
// 返回获取失败
return false;
}
// 释放锁
protected final boolean tryRelease(int releases) {
// 查询状态并-1
int c = getState() - releases;
// 如果释放锁的线程非获得所得线程,抛出异常
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 如果同步状态为0
if (c == 0) {
free = true;
// 将获得锁线程设置为null
setExclusiveOwnerThread(null);
}
// 重设同步状态
setState(c);
// 如果锁已经完全释放,返回true
return free;
}
// 判断当前线程是否为获得此锁
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
// 获取当前持有锁的线程
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
// 获取重入次数
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
// 判断锁是否已被使用
final boolean isLocked() {
return getState() != 0;
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
2. ReentrantLock 提供了公平锁和非公平锁
FairSync 和 NonfairSync 均继承于 Sync, 实现了不同的锁竞争机制
2.1 公平锁
按照时间先后顺序获取锁
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* 非阻塞式的获取公平锁
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
/*
hasQueuedPredecessors(),判断是否由线程在等待获得锁
如果没有等待线程,使用CAS设置同步状态
*/
if (!hasQueuedPredecessors() &&
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;
}
}
2.2 非公平锁
谁先拿到就是谁的
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
// 阻塞时获取锁
final void lock() {
// 如果同步状态为 0 ,将其设置为 1
if (compareAndSetState(0, 1))
// CAS 成功,则获得锁
setExclusiveOwnerThread(Thread.currentThread());
else
// CAS 不成功调用 AbstractQueuedSynchronizer 的 acquire()
acquire(1);
}
// 非阻塞式获取得公平锁,调用 sync 中的 nonfairTryAcquire()
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
上一篇: 操作DOM(一):创建节点、插入节点