我试图说服自己finally
子句中采取的行动发生在函数返回之前(在内存一致性意义上)。从JVM 规范中可以清楚地看出,在线程中,程序顺序应该驱动发生在关系之前 - 如果a在程序顺序中发生b ,则a 发生在 b之前。
但是,我没有看到任何明确说明最终在返回之前发生的事情,是吗?或者,编译器是否可以通过某种方式重新排序finally
子句,因为它只是记录日志。
激励示例:我有一个线程从数据库中获取对象并将它们放入 ArrayBlockingQueue,而另一个线程正在将它们取出。我有一些用于事件计时try
的finally
块,并且我在日志语句之前看到了返回的影响
线程 1:
public Batch fetch() {
try {
log("fetch()+");
return queryDatabase();
}
finally {
log("fetch()-");
}
...
workQueue.put(fetch());
线程 2:
log("take()+");
Batch b = workQueue.take();
log("take()-");
令我惊讶的是,它以意想不到的顺序打印出来。虽然,是的,不同线程中的日志记录语句可能会出现乱序,但至少有 20 毫秒的时间差。
124 ms : take()+
224 ms : fetch()+
244 ms : take()-
254 ms : fetch()-
请注意,这与finally trump return的问题并不完全相同。我不是在问将返回什么,而是在问内存一致性和执行顺序。