【问题标题】:Why do we need Atomic* classes if wrapper classes are already immutable?如果包装类已经是不可变的,为什么我们需要 Atomic* 类?
【发布时间】:2016-09-14 05:46:08
【问题描述】:

我最近遇到了来自java.util.concurrent.atomic 包的原子类。据我所知,不可变类在本质上默认是线程安全的,所以我们不需要同步它们。后来我才知道像 Integer、Boolean、Character 等包装类本质上是不可变的,那么为什么我们需要像 AtomicInteger 或 AtomicLong 这样的 Atomic* 类。另外,请解释一下AtomicReference是什么。

【问题讨论】:

  • 原子类是可变的
  • 因为......也许你想要一个不可变的原子类?
  • @Eran 我同意,但是包装类将在多线程环境中工作,那么为什么需要原子类。大卫的原因是他们创造它们的主要原因吗?
  • 仅使用不可变类,您可以共享的只是常量。我认为不需要太多的想象力就可以意识到有时您需要的不仅仅是常量。

标签: java multithreading concurrency


【解决方案1】:

原子类是可变的,但在修改方面具有强大的内存一致性保证。因此,它们的用途与不可变包装类不同。

Atomic* 类的真正优势在于它们公开了一个原子compare-and-swap 方法,这对于实现lock-free algorithms 非常有用。

与许多中级到高级并发工具一样,如果您无法想象为什么需要这样的工具,那么您可能不应该尝试使用它们。如果您在任何地方都坚持不变性或显式锁定,那么您可能不需要原子。

【讨论】:

    【解决方案2】:

    Here 是一个关于compareAndSet 原则的好问题。

    来自文档:

    • 这些方法的规范使实现能够使用现代处理器上可用的高效机器级原子指令。

    阅读atomic / volatile / synchronized 将帮助您保持它们之间的差异。

    【讨论】:

      【解决方案3】:

      你有没有想过当我有一个Integer(1)时,我怎样才能把它改成Integer(2),整数是不可变的。所以我需要创建一个新的并设置它的值,但这个过程不是原子的。

      【讨论】:

      • 原子!=不可变
      【解决方案4】:

      原子性的概念来自于事物是可变的。 我们希望将修改字段/变量的操作(可能是多个步骤,读取 -> 更新 -> 写入)作为原子操作。所以在多线程场景中,不应该有任何数据损坏。 java.util.concurrent.atomic 包为我们做这件事。 Wrapper 类是不可变的,我们不能修改它,需要创建一个新的实例。

      【讨论】:

        猜你喜欢
        • 2014-06-30
        • 1970-01-01
        • 1970-01-01
        • 2011-01-09
        • 2010-11-17
        • 1970-01-01
        • 1970-01-01
        • 2020-12-17
        • 1970-01-01
        相关资源
        最近更新 更多