【问题标题】:Can the `ConcurrentHashMap::get` method return a "dirty" valuekkkjjjjj?`ConcurrentHashMap::get` 方法能否返回一个“脏”值 kkkjjjjj?
【发布时间】:2018-10-25 06:19:12
【问题描述】:

在通过put 方法写入值时,如果另一个线程尝试读取同一个键的值,读取线程会得到什么?旧值、新值还是一些“垃圾”值?

【问题讨论】:

    标签: java multithreading java.util.concurrent concurrenthashmap


    【解决方案1】:

    如果第一个线程的put 操作已完成,第二个线程的get 将看到新值。否则,它将看到旧值。

    请注意,在此上下文中,“已完成”不是一个明确定义的概念。该操作可以被视为在put 调用返回之前完成。

    但您可以依靠两件事:

    • 第二个线程看不到垃圾引用。它始终是对有效对象的引用。
    • 第二个线程将1能够看到第一个线程在调用put之前对对象所做的所有写入。

    Java 内存模型保证了后者,这是 javadoc 所讨论的 happens-before 的结果。


    1 - 这假设在第一个线程的 put 和访问由 get 返回的对象的第二个线程之间的中间间隔内没有对对象的其他更新。

    【讨论】:

    • 在put调用返回之前可以认为操作已经完成。你的意思是说第二个线程对get的调用甚至可以在@987654328之前取回值吗? @call返回——表示值已经写入map,但是方法调用还没有返回
    • 基本上,是的。 put 完成工作和返回之间会有一个很小的窗口。 (我有点迂腐……)
    • 但是那个小窗口只有在钥匙上的锁被释放后才对吧?
    • 是的。 (但锁是在一个段上,不是钥匙。看源码。)
    【解决方案2】:

    来自Javadoc

    检索反映了最近完成更新操作在开始时保持的结果。 (更正式地说,给定键的更新操作与报告更新值的键的任何(非空)检索具有发生前的关系。)

    【讨论】:

    • 嗨,安迪·特纳,你能举个例子吗?
    猜你喜欢
    • 2021-09-21
    • 2016-07-07
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 2016-08-26
    相关资源
    最近更新 更多