【问题标题】:Should I synchronize to avoid visiblity issues when using java.util.concurrent classes?使用 java.util.concurrent 类时是否应该同步以避免可见性问题?
【发布时间】:2011-05-01 17:27:21
【问题描述】:

当使用任何 java.util.concurrent 类时,我是否仍需要同步对实例的访问以避免不同线程之间的可见性问题?

详细阐述这个问题

当使用 java.util.concurrent 的实例时,是否有可能一个线程修改该实例(即,将一个元素放入并发 hashmap 中)而后续线程将看不到修改?

我的问题源于 Java 内存模型允许线程缓存值,而不是在对值的访问不同步的情况下直接从内存中获取它们。

【问题讨论】:

    标签: java multithreading concurrency java.util.concurrent java-memory-model


    【解决方案1】:

    在 java.util.concurrent 包 Memory Consistency Properties 上,您可以查看该包的 Javadoc API:

    所有类的方法 java.util.concurrent 及其 子包将这些保证扩展到 更高级别的同步。在 特别是:

    • 将对象放入任何线程之前的线程中的操作 并发收集 happen-before 访问或删除该操作之后的操作 集合中的元素 另一个线程。
      [...]
    • “释放”同步器方法之前的操作,例如
      Lock.unlock、Semaphore.release 和
      CountDownLatch.countDown
      happen-before 成功“获取”方法之后的操作 比如Lock.lock, Semaphore.acquire, Condition.await, 和 CountDownLatch.await 上 另一个同步器对象 线程。
      [...]

    因此,这个包中的类确保了并发性,利用一组类进行线程控制(LockSemaphore 等)。这些类以编程方式处理 happen-before 逻辑,即管理并发线程的 FIFO 堆栈,锁定和释放当前和后续线程(即使用 Thread.wait()Thread.resume() 等。

    然后,(理论上)您不需要同步访问这些类的语句,因为它们以编程方式控制并发线程访问。

    【讨论】:

    • 不确定那是“答案”,它只是演示了同步的规范。我理解这个问题更多地是关于需要添加额外的同步..?
    • 你说得对,托比。我想知道我是否可以假设通过使用 java.utils.concurrent 类我不必担心可见性问题,即这些类是否需要同步。
    • 好的。我的错。我误解了这个问题。
    • 太棒了!!感谢 Tomas,“内存一致性属性”正是我所需要的!我很高兴我可以假设对 java.util.concurrent 类所做的更新是可见的。
    【解决方案2】:

    因为 ConcurrentHashMap(例如)被设计为在并发上下文中使用,所以您不需要进一步同步它。事实上,这样做可能会破坏它引入的优化。

    例如,Collections.synchronizedMap(...) 代表了一种使地图线程安全的方法,据我所知,它本质上是通过将所有调用包装在 synchronized 关键字中来工作的。另一方面,像 ConcurrentHashMap 这样的东西会在集合中的元素之间创建同步的“桶”,从而导致更细粒度的并发控制,因此在大量使用下减少锁争用。例如,它也可能不会锁定读取。如果你用一些同步访问再次包装它,你可能会破坏它。显然,您必须注意所有对集合的访问都是同步的,这是新库的另一个优势;您不必担心(尽可能多!)。

    java.lang.concurrent 集合可以通过同步实现它们的线程安全。在这种情况下,语言规范保证可见性。他们可以在不使用锁的情况下实现事物。我对此不是很清楚,但我认为这里会有相同的可见性。

    如果您在代码中看到看似丢失更新的内容,则可能只是竞争条件。 ConcurrentHashpMap 之类的东西会在读取时为您提供最新的值,而写入可能尚未写入。这通常是在准确性和性能之间进行权衡。

    重点是; java.util.concurrent 的东西是用来做这些东西的,所以我相信它可以确保可见性和使用 volatile 和/或不需要添加同步。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-14
      • 2014-11-25
      • 1970-01-01
      • 2018-10-04
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 2016-03-26
      相关资源
      最近更新 更多