假设你有下面的类

public class AccessStatistics {
  private final int noPages, noErrors;
  public AccessStatistics(int noPages, int noErrors) {
    this.noPages = noPages;
    this.noErrors = noErrors;
  }
  public int getNoPages() { return noPages; }
  public int getNoErrors() { return noErrors; }
}

和执行下面的代码

private AtomicReference<AccessStatistics> stats =
  new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));

public void incrementPageCount(boolean wasError) {
  AccessStatistics prev, newValue;
  do {
    prev = stats.get();
    int noPages = prev.getNoPages() + 1;
    int noErrors = prev.getNoErrors;
    if (wasError) {
      noErrors++;
    }
    newValue = new AccessStatistics(noPages, noErrors);
  } while (!stats.compareAndSet(prev, newValue));
}

在最后一行while (!stats.compareAndSet(prev, newValue))如何的compareAndSet方法的 确定平等 之间prevnewValue?需要对AccessStatistics类来实现的equals()方法?如果不是,为什么? Javadoc中说明的用于AtomicReference.compareAndSet以下

  

原子方式设置的值,以给定的更新值,如果当前值==预期值。

...但这种说法似乎很一般,我已经在读的AtomicReference教程从未建议实施了包裹在一个的AtomicReference类的equals()方法。

如果包裹在的AtomicReference类都必须实现equals()然后为对象比AccessStatistics我想可能更快来同步更新对象的方法和不使用的AtomicReference更加复杂。

有帮助吗?

解决方案

有完全一样,如果您使用了==运算符的refrerences进行比较。这意味着,引用必须指向同一个实例。的Object.Equals()不被使用。

其他提示

其实,它的的比较上一个和NEWVALUE!

相反,它存储的统计信息内PREV并且仅当那些是相同的,它更新存储到NEWVALUE统计内的值的值进行比较。正如上面所说的,它使用等号运算符(==)这样做。这意味着,当ANLY先前所指向的相同的对象被存储在统计信息的统计信息将被更新。

这只是检查对象引用相等(又名==),因此,如果通过的AtomicReference持有对象引用改变了你得到了引用后,它不会改变的参考,所以你必须重新开始。

以下是一些的AtomicReference的源代码的。的AtomicReference是指一个对象引用。此引用中,如下所示的AtomicReference实例挥发性成员变量。

private volatile V value;

的get()简单地返回变量的最新值(作为挥发物在一做方式“之前发生”)。

public final V get()

以下是的AtomicReference的最重要的方法。

public final boolean  compareAndSet(V expect, V update) {
        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}

在compareAndSet(期望的那样,更新)方法调用不安全类的Java的compareAndSwapObject()方法。此方法不安全的呼叫调用本机呼叫,这将调用单个指令到处理器。 “期望”和“更新”每一个参考对象。

如果且仅当的AtomicReference实例成员变量“值”指的是相同的目的是通过“期望”,“更新”现在被分配给该实例变量,和“真”返回参照。否则,返回false。整个事情是自动完成的。没有其他线程可以拦截之间。由于这是一个单处理器操作(现代计算机体系结构的魔法),它往往比使用同步块更快。但请记住,当多个变量需要用原子方式更新,的AtomicReference也无济于事。

我想补充完全成熟的运行代码,它可以在蚀运行。这将明确很多混乱。这里22用户(神话线程)正在尝试预订20个席位。以下是代码片段后跟完整代码。

代码段,其中22个用户试图预定20个座位。

for (int i = 0; i < 20; i++) {// 20 seats
            seats.add(new AtomicReference<Integer>());
        }
        Thread[] ths = new Thread[22];// 22 users
        for (int i = 0; i < ths.length; i++) {
            ths[i] = new MyTh(seats, i);
            ths[i].start();
        }

以下是GitHub的链接,那些谁愿意看到正在运行的完整的代码是小而简洁。 https://github.com/sankar4git/atomicReference/blob/master/Solution。的java

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top