其实关于这一点,网上大部分人都会说,要 await()必然要先 lock(),既然 lock()了就表示没有竞争,没有竞争自然也没必要使用 volatile+CAS 的机制去保证什么。所以 firstWaiter 不需要是 volatile 的。
但是实际上我感觉还是会有问题,比如你执行下面这段程序:
final Lock lock=new ReentrantLock();
Condition Emptycondition = lock.newCondition();
Emptycondition.await(); //这样会抛出异常
比如你让一个子线程去做上面的事,会抛出异常,因为 await()的时候没有获取锁呢。但是在抛出异常之前,你已经执行了一部分代码了:
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);//在这里抛出的异常,意味着已经执行了 addConditionWaiter
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {//具体的说,是这里抛出异常了
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed)//抛出异常后,failed 为真,但善后处理只是将 node 的状态变成 CANCELLED
node.waitStatus = Node.CANCELLED;
}
}
再来看 addConditionWaiter 的逻辑:
private Node addConditionWaiter() {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;//对不保证可见性的变量进行赋值了
else
t.nextWaiter = node;
lastWaiter = node;//对不保证可见性的变量进行赋值了
return node;
}
好了,现在执行完我的那三行测试代码后,Emptycondition 的条件队列上有了一个 node,而且这个 node 包装了一个死掉的线程。因为抛出异常
现在假设有另一个线程执行正常流程的代码:
final Lock lock=new ReentrantLock();
Condition Emptycondition = lock.newCondition();
lock.lock();
try{
Emptycondition.await();
} finally {
lock.unlock();
}
现在条件是:
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.