【问题标题】:Java Atomic Variable set() vs compareAndSet()Java 原子变量 set() 与 compareAndSet()
【发布时间】:2013-10-14 20:07:17
【问题描述】:

我想知道原子类中 set() 和 compareAndSet() 的区别。 set() 方法是否也确保原子过程?例如这段代码:

public class sampleAtomic{
    private static AtomicLong id = new AtomicLong(0);

    public void setWithSet(long newValue){
        id.set(newValue);
    }

    public void setWithCompareAndSet(long newValue){
        long oldVal;
        do{
            oldVal = id.get();
        }
        while(!id.compareAndGet(oldVal,newValue)
    }
}

这两种方法是否相同?

【问题讨论】:

    标签: java set atomic compare-and-swap


    【解决方案1】:

    setcompareAndSet 方法的作用不同:

    • compareAndSet :如果当前值等于 (==) 预期值,则自动将值设置为给定的更新值。
    • set :设置为给定值。

    set() 方法是否也保证了原子进程?

    是的。它是原子的。因为set 新值只涉及一项操作。下面是set方法的源码:

    public final void set(long newValue) {
            value = newValue;
    }
    

    【讨论】:

    • 感谢您的回答。我忘了检查源代码。你说 set 方法是原子的是对的,但原因不是因为它只有一个操作。自动类有一个名为 value 的成员变量,该变量是 volatile 的(上面 set 方法体中的那个),所以 set 方法应该是线程安全的。
    • 你确定Atomic 类是原子的,因为它们使用易失性变量来维护它们的内部状态。如果你定义一个 volatile 变量volatile long value,像value++ 这样的操作是原子的吗?答案是否定的。这个操作不是原子的;它实际上是三个不同的操作——取值,加一,写回更新的值。同时,另一个线程可以更改value。所以拥有volatile 变量并不能保证原子性。一个操作/进程是atomic,如果它们提供对原子更新的支持。
    • 现在,set 操作是原子的,因为它只有一个操作:value = newValue;,即使 value 未定义 volatile 也是原子的。这里 value 被定义为 volatile 以使用它们提供的可见性保证 - 一个线程所做的更改始终对其他线程可见。
    【解决方案2】:

    从下面打开的 jdk 代码可以看出。

    http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/atomic/AtomicLong.java#AtomicLong.set%28long%29

    set 只是分配值,compareAndSet 正在执行额外的操作以确保原子性。

    http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/atomic/AtomicLong.java#AtomicLong.compareAndSet%28long%2Clong%29

    在设计任何原子操作时都需要考虑返回值(布尔值)。

    【讨论】:

      猜你喜欢
      • 2020-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-20
      相关资源
      最近更新 更多