java - LongAdder:try 块怎么会失败?
问题描述
我正在LongAdder
详细分析算法。LongAdder
扩展类Striped64
,在该类中,基本方法是retryUpdate
. 以下代码取自该方法;在链接的源代码中,它占据了第 212-222 行:
try { // Recheck under lock
Cell[] rs; int m, j;
if ( (rs = cells) != null &&
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;
created = true;
}
} finally {
busy = 0;
}
问题:这个try
块怎么会失败?
注意数组访问
rs[j = (m - 1) & h]
不应抛出 an,IndexOutOfBoundsException
因为按位与运算的结果始终小于或等于其整数参数的最小值,因此 0 <= j <= m-1 在数组的范围内。
解决方案
Thread.stop
由于从另一个线程调用不推荐使用的方法,此代码 - 以及版本 11 之前的任何其他 Java 代码 - 可能会失败。这会导致在ThreadDeath
目标线程中抛出错误,可能随时发生。但是,线程至少可以存活足够长的时间以使finally
块执行。
该Thread.stop
方法已被弃用,因为这种行为使其“本质上不安全”:
为什么不推荐使用 Thread.stop?
因为它本质上是不安全的。停止线程会导致它解锁所有已锁定的监视器。(当 ThreadDeath 异常向上传播堆栈时,监视器被解锁。)如果以前受这些监视器保护的任何对象处于不一致状态,则其他线程现在可能会查看这些处于不一致状态的对象。据说这些物体已损坏。当线程对损坏的对象进行操作时,可能会导致任意行为。这种行为可能很微妙且难以检测,也可能很明显。与其他未经检查的异常不同,ThreadDeath 以静默方式杀死线程;因此,用户没有警告他的程序可能已损坏。损坏可以在实际损坏发生后的任何时间出现,甚至在未来几小时或几天内。
从理论上讲,如果执行对象的线程从另一个线程停止,则可以以这种方式编写代码,以防止对象处于无效状态。Thread.stop
也就是说,如果可以随时调用,则很难保证有效状态,甚至尝试这样做也不常见,因此这不太可能是作者的意图。(如果是,代码可能会有注释解释它。)
推荐阅读
- slider - PySimpleGUI 滑块是否有小数范围?
- openxml - 通过 OpenXml SDK 的 XLSX 文件有效和无效
- r - geom_label_repel 和 geom_label 的错误图例
- javascript - 如何为每个用户读取和写入 firestore 中的字段?
- c++ - 为什么 std::set 在 std::vector 上优于 std::priority_queue 在 std::deque 上优于 std::priority_queue?
- shell - 鱼壳似乎忽略了 LD_LIBRARY_PATH?
- javascript - 如何在标签上使用点击事件
- sql-server - 在异常情况下使整个 SSIS 包失败
- python - Python:AttributeError:“ApiClient”对象没有属性“configure_jwt_authorization_flow”
- angular - 使用 Jasmine 更改模拟服务成员的值