【发布时间】:2021-04-16 22:42:26
【问题描述】:
我注意到 Oracle 的 JDK 和 Open JDK 之间的 ConcurrentHashMap.computeIfAbsent 方法的语义存在严重差异。这很令人惊讶,所以我想记录一下,看看其他人是否注意到了这个问题,或者我是否误解了某些内容。
根据 Oracle JDK 的 Javadoc(从 v8 开始,一直到 v15),调用 mappingFunction 的语义是:
整个方法调用是原子执行的,因此每个键最多应用一次函数。
但是,当从两个不同的线程同时访问密钥时,我注意到该函数在我的程序中被调用了两次。深入挖掘,我注意到 Open JDK 的文档指定了不同的语义:
整个方法调用都是原子执行的。如果键不存在,则每次调用此方法时,提供的函数只调用一次,否则根本不调用。
这在行为上有很大的不同,并且与我在程序中观察到的一致。在我看来,Open JDK 的实现用处不大,因为正在构建的资源通常非常昂贵,并且应该最多创建一次。
【问题讨论】:
-
对我来说“最多一次”与“仅一次或根本没有”似乎没有什么不同。也许您需要更具体地说明您的担忧?
-
OpenJdk 运行在 OracleJdk 之前,所以这个变化最终可能会成为 OracleJdk 的一部分。仅供参考,2019 年 11 月对 OpenJdk 进行了更改 - 这是提交,但抱歉我目前没有时间进一步调查:github.com/openjdk/jdk/commit/…
-
@John3136,再次阅读 javadoc sn-ps。 OpenJDK 指定该函数将被调用“如果键不存在,则每次调用此方法一次”,而 Oracle JDK 指定该函数“每个键最多调用一次”。大不同。
-
@racraman,非常有趣!感谢您分享。
-
由于discussion,JavaDoc 被改写以试图更精确。
标签: java concurrency java.util.concurrent