【问题标题】:Can AtomicInteger replace synchronized?AtomicInteger 可以代替同步的吗?
【发布时间】:2010-11-17 23:32:01
【问题描述】:

java.util.concurrent.atomic 包的 javadoc 说明如下:

一个小的类工具包, 支持无锁线程安全 对单个变量进行编程。

但我在任何 AtomicInteger 或 AtomicBoolean 类中都看不到任何线程安全(同步或锁定)代码。

那么,这两个是一样的吗:

1.

int i;
synchronized(this){i++;}

2.

AtomicInteger i = new AtomicInteger();
i.getAndIncrement();

更新:感谢您的回答。使用 AtomicInteger 时需要 volatile 吗?

【问题讨论】:

    标签: java


    【解决方案1】:

    它们将提供相同的原子性。您唯一必须注意的是,任何时候您阅读 i 时都必须使用同步来包装它

    synchronized(this){ return i;}
    

    编辑以回答您的编辑:

    对于您的 AtomicInteger,Volatile 不是必需的。证明声明 AtomicInteger final。您需要 AtomicInteger 为 volatile 的唯一原因是 AtomicInteger 字段本身是否发生变化。类似于:

    volatile AtomicInteger i = new AtomicInteger(0);
    
    public void work(){
        i.incrementAndGet();
        //...do some other stuff
        i = new AtomicInteger(10);//because the field i is changing the field needs to be volatile 
    }
    

    您可以想象,情况并非如此,因此您不必担心该字段易变。

    【讨论】:

      【解决方案2】:

      它们在功能上是等价的,但有细微的差别。 synchronized 有在this 上获取和释放监视器的开销,而AtomicInteger 是通过本机方法调用实现的,因此会明显更快。

      【讨论】:

      • 您是否有来源表明 AtomicInteger 的本机方法调用比使用 synchronized 快​​得多?
      • 阅读 java.util.concurrent.atomic 的 Javadoc。所述目的是允许使用硬件原子原语。不需要实现,但大多数现代硬件都支持原子 CAS,这会更快。
      【解决方案3】:

      是的,它们在功能上是等效的。

      如果您处于超高争用环境中,您可能会看到性能差异,但这是极不可能的。

      【讨论】:

        【解决方案4】:

        AtomicInteger 在下面使用 sun.misc.Unsafe 来执行原子更新。

        所以,回答您的问题,是的,AtomicInteger 是线程安全的

        【讨论】:

          【解决方案5】:

          使用 AtomicInteger 时需要 volatile 吗?

          不一定。考虑你的例子:

          • 如果i 是一个局部变量,或者
          • 如果ifinal 属性,或者
          • 如果当前线程和初始化(或最后更新)i 变量的线程在该事件之后已同步,

          那么你是否将i 声明为 volatile 没有区别。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-12-02
            • 1970-01-01
            • 1970-01-01
            • 2012-07-25
            • 1970-01-01
            • 2021-03-18
            • 2020-12-06
            • 1970-01-01
            相关资源
            最近更新 更多