我已阅读以下经典著名文章:The "Double-Checked Locking is Broken" Declaration
我有一个问题:
事实上,假设computeHashCode函数始终返回 结果相同且没有副作用(即幂等),您可以 甚至摆脱了所有同步。
// Lazy initialization 32-bit primitives
// Thread-safe if computeHashCode is idempotent
class Foo {
private int cachedHashCode = 0;
public int hashCode() {
int h = cachedHashCode;
if (h == 0) {
h = computeHashCode();
cachedHashCode = h;
}
return h;
}
// other functions and members...
}
本文是针对Java 4编写的。它对Java 8+仍然有效吗?
computeHashCode()
只会被调用一次吗?
答案 0 :(得分:4)
否,它可以多次执行。同步“使”更改“散布”到其他线程,如果没有它,则从理论上讲,一个线程中所做的更改永远无法在该线程外进行通信。
但是,本文并没有说computeHashCode
会被精确地调用一次,只是竞争条件不会引起任何问题。 int
的写保证是原子的,并且如果computeHashCode
是幂等的(这要求类及其字段有效地是最终的),则只需用相同的值覆盖以前的值,所以没什么不好的发生。
答案 1 :(得分:1)
不,它不能保证只能被调用一次,但这无关紧要。
如果computeHashCode
是幂等的,则额外调用它是无效的,因此线程不会相互干扰。
答案 2 :(得分:1)
与您发表的同一篇文章
JDK5和更高版本扩展了volatile的语义,从而使系统 不允许对volatile的写入进行重新排序 以前的任何读或写操作,以及对volatile的读操作都不能 关于以下任何读或写重新排序。
通过此更改,可以使Double-Checked Locking惯用语生效 通过声明helper字段是可变的。这在以下情况下不起作用 JDK4和更早版本。
这意味着从Java 5开始,双重检查锁定是安全的。
computeHashCode()是否只会被调用一次是真的吗?
不。该方法不以任何方式同步。但是,它是线程安全的,因为它是幂等的。