为什么ConcurrentHashMap中的HashEntry是最终的?

时间:2013-08-30 19:59:14

标签: java multithreading collections java.util.concurrent concurrenthashmap

我将在jdk 7中查看ConcurrentHashMap的源代码并且几乎没有问题。我已经在StackOverFlow上完成了有关CHM的所有问题,但找不到答案。

  1. CHM中的get()操作是否保证获得put()的正确值 其他线程?我问这是因为获取不是synchronized,除非它 看到空值。 null值如何确保存在相同的记录 由其他线程更新,然后get与lock一起使用?

  2. 这与存储键和值的HashEntry静态类有关。

    一个。为什么这堂课最后?它只是为了确保没有人对它进行子类化吗? 如果有人将其子类化,会发生什么 - 这有什么问题?

    湾如何使下一个字段最终有助于获得线程安全性?

    ℃。为什么Key也是最终的? (我不确定为什么Key在HashMap中也是最终的)

1 个答案:

答案 0 :(得分:6)

  

CHM中的get操作是否保证得到其他线程的put值正确?

只要put()在调用get()之前完成,肯定会得到保证。 CHM在内部使用volatile访问和其他锁​​定以确保数据同步,而不一定是synchronized关键字。

  

我问这是因为get不会同步,除非它看到null值。 null值如何确保其他线程正在更新相同的记录,然后get与lock一起使用?

我假设你指的是这个javadoc:

  

因为值字段是易失性的,而不是最终的,所以对于非同步读取器,Java内存模型在通过数据争用读取时看到null而不是初始值是合法的。尽管实际上不可能实现重新排序,但是如果在非同步访问方法中看到null(预初始化)值,则Segment.readValueUnderLock方法将用作备份。

这是试图解释该值不是最终的,因此构造函数中的初始化可以重新排序,读者可以看到空值。我假设这就是为什么不允许CHM存储空值的原因。这允许他们测试null,然后在synchronized块内进行另一次。

有关重新排序的构造函数的详细信息,请参阅:Is reordering of instance initialization and assignment to a shared variable possible?

  

为什么HashEntry课程最终?是否只是为了确保没有人将其子类化?

是。这确保了类不能被子类化。这确保了不变性。如果有人将其子类化,他们可能会改变字段的可见性并破坏并发合同。

  

如何使下一个[[field]] final有助于获得线程安全性?

next字段(以及keyhash字段)为final,因为这可确保字段在构造函数中完全初始化。这确实提高了线程安全性,因为优化器不能在构造函数结束之后重新排序初始化,并且所有线程都保证看到数据。

请参阅上文,了解有关value字段以及它们如何防范 {/ 1}}允许final覆盖的信息。

  

为什么Key也是最终的? (我不确定为什么Key也是HashMap中的最终版)

put(...)相同的答案。