【问题标题】:Why is HashEntry in ConcurrentHashMap final?为什么 ConcurrentHashMap 中的 HashEntry 是最终的?
【发布时间】:2013-08-30 19:59:13
【问题描述】:

我正在查看 jdk 7 中 ConcurrentHashMap 的源代码,并且有几个问题。我已经在 StackOverFlow 上浏览了所有关于 CHM 的问题,但找不到答案。

  1. CHM 中的get() 操作能否保证得到正确的put() 值? 其他线程?我问这个,因为 get 不是 synchronized 除非它 看到空值。空值如何确保相同的记录 被其他线程更新,然后get被锁使用?

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

    一个。为什么这门课是决赛?只是为了确保没有人继承它吗? 如果有人继承它会发生什么——这有什么问题吗?

    b.将下一个字段设为 final 如何有助于获得线程安全?

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    我假设您指的是这个 javadoc:

    因为 value 字段是 volatile 的,而不是 final 的,所以在 Java 内存模型中,非同步读取器在通过数据竞争读取时看到 null 而不是初始值是合法的。虽然导致这种情况的重新排序实际上不太可能发生,但 Segment.readValueUnderLock 方法用作备用方法,以防在未同步的访问方法中看到空(预初始化)值。

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

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

    为什么HashEntry 类是final?只是为了确保没有人继承它吗?

    是的。这确保了类不能被子类化。这确保了不变性。如果有人对其进行子类化,他们可以更改字段的可见性并破坏并发契约。

    将 next [[field]] 设为 final 如何有助于获得线程安全?

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

    有关value 字段的信息以及它们如何防止它不是final 允许put(...) 覆盖,请参见上文。

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

    HashEntry 的答案相同。

    【讨论】:

    • Re:“它不会编译 [如果有人继承 HashEntry]”:这似乎是一个非答案。 OP在问“为什么这是final,有人继承它会有什么问题?”你的答案是“有人继承它的问题是它不会编译,因为它是final”。
    • @ruakh - 这个问题的真正答案在下一个回复中:因为我认为这可以确保不变性。如果有人对其进行子类化,他们可以更改字段的可见性并破坏并发合同。
    • Re: "[making next final] 确保不变性。如果有人对其进行子类化[...]":类是final,因此没有子类化风险;所以你不能引用子类化的风险来解释为什么其中一个字段是final
    • @DaoWen:不,下一个响应是指final 的不同出现。 (无论如何,没有理由包含一个乏味的非答案,即使它紧随其后是一个真正的答案。)
    • 我已经扩展了@ruakh 的答案以指出 why 它不能被子类化的原因是由于可见性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    • 1970-01-01
    • 2019-03-24
    • 2011-03-29
    相关资源
    最近更新 更多