new ReentrantLock();加锁流程:
//默认执行NonfairSync.lock();
final void lock() {
//cas 0 -> 1 ,如果操作成功,将当前线程设置为独占线程
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//如果操作失败
acquire(1);
}
public final void acquire(int arg) {
//tryAcquire(arg)尝试获取锁,如果获取锁失败返回false,否则返回true
if (!tryAcquire(arg) &&
//尝试获得锁,如果当前线程被中断 返回 true,否则返回false
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//获得锁失败,且当前线程的中断状态为true,则重新去尝试
selfInterrupt();
}
tryAcquire()最终默认调用ReentrantLock.NonfairSync.nonfairTryAcquire();
final boolean nonfairTryAcquire(int acquires) {
//获取当前线程
final Thread current = Thread.currentThread();
//获取state值
int c = getState();
//0 代表没有线程占用锁
if (c == 0) {
//cas 将 0 改为 1
if (compareAndSetState(0, acquires)) {
//cas 成功之后 将独占线程改为当前线程
setExclusiveOwnerThread(current);
//返回成功
return true;
}
}
//如果有线程获取当前线程(也就是当前线程是独占线程)
else if (current == getExclusiveOwnerThread()) {
//state值加1
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
//保存新的state值
setState(nextc);
//返回true
return true;
}
//否则,就返回false
return false;
}
AbstractQueuedSynchronizer.addWaiter(Node.EXCLUSIVE);解析
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
//尾节点赋值给pred;
Node pred = tail;
//尾节点不为空
if (pred != null) {
//当前的节点prev指针指向现在的尾节点
node.prev = pred;
//cas 将当前尾节点 替换为 node节点
if (compareAndSetTail(pred, node)) {
//当前尾节点的next指针指向 node节点
pred.next = node;
return node;
}
}
//如果尾节点为空或者cas替换失败,则执行入队操作
enq(node);
return node;
}
//入队操作:将当前节点设置为尾节点,并更新当前节点和替换前的尾节点的指针指向
private Node enq(final Node node) {
for (;;) {
//把尾节点赋值给一个变量
Node t = tail;
//如果尾节点为空
if (t == null) {
//新建一个节点,设置为头节点
if (compareAndSetHead(new Node()))
//把头节点赋值尾节点
tail = head;
} else {
//如果尾节点不为空,当前节点的prev指针指向尾节点
node.prev = t;
//cas 将当前节点设置为尾节点
if (compareAndSetTail(t, node)) {
//替换前的尾节点的next指针指向当前节点
t.next = node;
return t;
}
}
//如果cas 替换尾节点 失败,则循环执行,直到成功为止
}
}
AbstractQueuedSynchronizer.acquireQueued(addWaiter(Node.EXCLUSIVE), arg);
//已经入队的非中断线程再次尝试获取锁
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;
}
//如果当前节点的前驱节点不是头节点 或者 获得锁失败,则阻塞当前节点线程等待当前节点的线程被唤醒,并判断中断状态
if (shouldParkAfterFailedAcquire(p, node) &&
//阻塞当前线程,等待当前线程被唤醒后,判断当前线程的中断状态
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
shouldParkAfterFailedAcquire(p, node)细节如下:
//获取锁失败的线程检查并更新node中的waitStatus。如果线程应该被阻塞返回true。
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
//获取前一个节点的等待状态
int ws = pred.waitStatus;
//-1,代表前一个节点被阻塞中,需要唤醒
if (ws == Node.SIGNAL)
return true;
if (ws > 0) {
// > 0 代表前一个节点被取消,就递归往找waitStatus > 0的节点信息
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
//找到后,将此节点的next指针指向当前节点
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
* waitStatus 必须是0 或者 -3(表示可以共享获得)。表明我们需要唤醒,但是还没有阻塞。调用者需要重试去保证在阻塞操作之前不能获取成功
*/
//cas 将 前一个节点的waitStatus 改为 -1(需要唤醒)
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
//返回false
return false;
}
private final boolean parkAndCheckInterrupt() {
//阻塞当前线程
LockSupport.park(this);
//当前线程被唤醒后,判断当前线程的的中断状态
//这里有一个非常重要的知识点:唤醒阻塞线程的方式 1.unpark 2.interrupt
return Thread.interrupted();
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。