在java的ReentrantLock 的unlock()
->release()
->unparkSuccessor()
方法中
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
//................
}
关于compareAndSetWaitStatus这段的作用是什么呢? 我研究了下
假设AB两线程,A线程先执行,准备走unlock时切换到B,B线程第一次执行到lock()
->acquire()
->acquireQueued()
->shouldParkAfterFailedAcquire()
方法时
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
return true;
if (ws > 0) {
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
当B线程走过到else代码块后,时间片用完此时head节点状态为-1
然后回到A线程执行unlock()
->release()
->unparkSuccessor()
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
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);
}
释放了锁,然后将head节点的状态改为了0,然后回到B线程
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;
}
//B线程执行完方法后返回到这里
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
那么B线程继续for循环,之后就获取到了锁,并置空了head节点,所以A线程在unlock()
中修改的head状态并没有什么作用
不是太明白这个步骤,而且注释上写了是允许这个cas失败的,这点也不是太明白