java - 为什么ConcurrentHashMap中的HashEntry是final的?

标签 java multithreading collections java.util.concurrent concurrenthashmap

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

  1. CHM 中的 get() 操作能否保证通过以下方式获取 put() 的正确值 其他线程?我问这个问题是因为 get 不是同步,除非它 看到空值。空值如何确保相同的记录 被其他线程更新然后get和lock一起使用?

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

    a.为什么这门课是期末课?只是为了确保没有人继承它吗? 如果有人继承它会发生什么——这有什么问题吗?

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

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

最佳答案

Is get operation in CHM guaranteed to get correct value of put by other thread?

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

I am asking this as get is not synchronized unless it sees the null value. How null value ensures that same record is being updated by other thread and then get is used with lock?

我假设您指的是这个javadoc:

Because the value field is volatile, not final, it is legal wrt the Java Memory Model for an unsynchronized reader to see null instead of initial value when read via a data race. Although a reordering leading to this is not likely to ever actually occur, the Segment.readValueUnderLock method is used as a backup in case a null (pre-initialized) value is ever seen in an unsynchronized access method.

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

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

Why is the HashEntry class final? Is it just to make sure nobody subclasses it ?

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

How does making next [[field]] final helps in getting thread safety?

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

有关 value 的信息请参阅上文场以及他们如何防范它 final这允许 put(...)覆盖。

Why is Key also final? (I am not sure why Key is final in HashMap also)

HashEntry相同的答案.

关于java - 为什么ConcurrentHashMap中的HashEntry是final的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18540611/

相关文章:

java - 将用户输入存储在不是从 0 开始的数组中

java - 将一个数组分配给另一个数组

java - 如何打印循环中遇到的最大数字?

java.util.logging.SimpleFormatter.format 毫秒

C++ 维护子类对象的混合集合

用于集合的 WPF 绑定(bind)转换器

java - OSGi DS 服务配置和 ServiceTracker

Java 管道输入/输出流通信中存在大量延迟

c - 实现用户级线程库启动一个新线程[作业]

Java - 线程状态异常