【问题标题】:Thread safety - reading mutable objects (java)线程安全——读取可变对象(java)
【发布时间】:2014-02-17 09:59:04
【问题描述】:

我有一个共享资源——一个简单的 POJO 包装了一个 HashMap——它将在启动时初始化一次,然后只能被许多线程读取,可能同时读取(上下文是一个 Web 应用程序)。我需要同步对对象的访问(或者使用并发哈希)还是安全地进行多个同时读取?同步会增加大量开销吗?

【问题讨论】:

    标签: java thread-safety readonly


    【解决方案1】:

    如果您确保所有写入发生在所有读取之前,您可以跳过对该映射的读取访问同步。其含义在JLS 7 chapter 17.4.5 中有描述。

    实际上,您必须确保在任何其他将访问它的线程启动之前填充HashMap,并且在此之后不会修改其内容。

    此解决方案有效的原因是Thread.start() 调用强制同步,因此保证在该调用之前所做的所有更改在该调用之后对新旧线程都是可见的。如果您在调用之后修改对象,则此保证将丢失,并且需要同步访问。

    【讨论】:

    • 听起来比实际简单。在这种情况下,您将使用对otherThread.start() 的调用保证该调用之前的任何修改对otherThread 可见的事实。如果您以某种不同步的方式将映射的引用传递给已经运行的线程,您将失去保证(AFAIK pastebin.com/p3mpbNxv 应该有这个问题。)以正确的顺序执行的代码并不能保证它实际上是按该顺序发生的除非你做一些事情来保证这种发生前的关系。
    • @zapl 我指向 JLS 并展示了一个简单实用的解决方案。我知道幕后发生了什么,这个问题的作者可能会从给定的 JLS 章节中自己学习,或者认为我写的内容是理所当然的。不管怎样,在这种情况下,他会很好。
    • 评论的原因是我觉得你第二段中的关键点如果你不知道的话很难看出。因此,它或多或少是针对读者/提示您如何 IMO 改进答案。
    【解决方案2】:

    如果您确定只需要执行读取操作,则不需要同步。这也是同样的原因有不同的锁——在ReadWriteLock中读写。

    ReadWriteLock 维护一对关联的锁,一个用于只读操作,一个用于写入。只要没有写者,读锁可能被多个读线程同时持有。写锁是独占的。

    由于您没有编写器,因此无需同步。

    【讨论】:

      【解决方案3】:

      由于多次读取的结果不依赖于事件的顺序,我会说你没有遇到竞争条件 (http://en.wikipedia.org/wiki/Race_condition),因此没有必要同步访问。

      【讨论】:

        猜你喜欢
        • 2012-08-07
        • 2011-01-24
        • 2013-06-23
        • 2016-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-13
        相关资源
        最近更新 更多