最后是否会返回“发生”?

| 我试图说服自己,在函数返回之前(在内存一致性的意义上),在
finally
子句中采取的动作已经发生。从JVM规范中可以很明显地看出,在线程内,程序顺序应该驱动关系发生在关系之前-如果在程序顺序中发生b,则发生在b之前。 但是,我没有看到任何明确说明最终会在返回之前发生的东西,是吗?或者,编译器是否可以通过某种方式重新排序
finally
子句,因为它只是在记录日志。 激励示例:我有一个线程从数据库中提取对象,并将其放入ArrayBlockingQueue中,而另一个线程将其取出。我有一些
try
-
finally
块用于事件计时,并且我在log语句之前看到返回的影响 线程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()-
请注意,这与最终的王牌回报并不完全相同。我不是要返回什么,而是要询问内存一致性和执行顺序。
已邀请:
@David Heffernan有正确答案。 JLS规范在第14.17节中讨论了return语句的行为(包括return语句如何与finally块交互)。从那里复制(重点是我的): 带有表达式的return语句 尝试将控制权转移给 包含的方法的调用者 它;表达式的值 成为方法的价值 调用。更确切地说,执行 首先这样的回报声明 计算表达式。如果 对表达式的评估完成 突然由于某种原因,然后 return语句突然完成 是因为。如果评价 表达式正常完成, 产生一个值V,然后返回 语句突然完成, 原因是返回值为V的收益 该表达式的类型为float并且为 而非FP-strict(第15.4节),则该值 可能是浮点数的元素 值集或 浮点扩展指数值集 (第4.2.3节)。如果表达式是类型 加倍且不受FP限制,则 值可能是 双重值集或 双扩展指数值集。 可以看出,回报 语句总是突然完成。 前面的描述说 “试图转移控制权” 不只是“转移控制权”,因为 如果有任何try语句 (§14.20)在方法中或 尝试块包含的构造函数 返回语句,然后最后 这些try语句的子句将 被执行到最里面 最外层,在控制之前 转移给 方法或构造函数。突如其来 最终条款的完成可以 破坏控制权的转移 由return语句启动。
queryDatabase()
的呼叫首先发生。然后是最后一块。然后控制离开该函数(即
return
)。
the0ѭ子句无论shall2ѭ块的结果或行为如何均应执行,因此
finally
要在before8ѭ之前执行。
如果只使用一个线程,则应该看到““ take +,fetch +,fetch-,take- \”。在您的示例中,它是多线程的,因此您不确定首先发生什么。

要回复问题请先登录注册