使用Java'的模块化增量;s原子类

使用Java'的模块化增量;s原子类,java,modulo,atomicity,Java,Modulo,Atomicity,我感到惊讶的是,Java的AtomicInteger和AtomicLong类没有模块化增量的方法(因此,在达到极限后,该值会变为零) 我想我肯定错过了一些明显的东西。最好的方法是什么 例如,我希望在线程之间共享一个简单的int,并且我希望每个线程都能够增加它,比如mod 10 我可以创建一个使用同步/锁定的类,但是有更好、更简单的方法吗?当您从中读取值时,只需修改10即可 public class AtomicWrappingCounter { private final AtomicLon

我感到惊讶的是,Java的AtomicInteger和AtomicLong类没有模块化增量的方法(因此,在达到极限后,该值会变为零)

我想我肯定错过了一些明显的东西。最好的方法是什么

例如,我希望在线程之间共享一个简单的int,并且我希望每个线程都能够增加它,比如mod 10


我可以创建一个使用同步/锁定的类,但是有更好、更简单的方法吗?

当您从中读取值时,只需修改10即可

public class AtomicWrappingCounter {
  private final AtomicLong counter = new AtomicLong();
  private final int max;

  public AtomicWrappingCounter(int max) {
    this.max = max;
  }

  public int get() {
    return (int) (counter.get() % max);
  }

  public int incrementAndGet() {
    return (int) (counter.incrementAndGet() % max);
  }
}

显然,如果您可能会将此计数器的增量超过
Long.MAX_VALUE
倍,则无法使用此方法,但9/5百万是增加的很多倍(大约292年,每纳秒1次!).

我认为最简单的方法是自己构建一个包装计数器,将其值存储在原子整数中,类似

public class AtomicWrappingCounter {
    private AtomicInteger value;
    private final int max;

    public AtomicWrappingCounter(int start, int max) {
        this.value = new AtomicInteger(start);
        this.max = max;
    }

    public int get() {
        return value.get();
    }

    /* Simple modification of AtomicInteger.incrementAndGet() */
    public int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = (current + 1) % max;
            if (value.compareAndSet(current, next))
                return next;
        }
    }
}

为什么
AtomicInteger
本身不提供类似的东西?谁知道呢,但我认为并发框架作者的意图是提供一些构建块,您可以使用它们更好地创建自己的高级函数。

addModular()
方法中添加
同步的
修饰符或块有什么困难

原子类之所以没有这个功能,是因为它们基于当前CPU提供的功能,如果不使用锁或matt建议的其他更复杂且可能效率低下的算法,模块化算法就无法实现

我很惊讶Java的AtomicInteger和AtomicLong类没有模块化增量的方法

当一个标准类不包含“bells和whistles”来支持各种不寻常的用例时,不要感到惊讶。设计师必须在某个地方划出一条线来区分他们包括什么和不包括什么。趋势是支持常见用例和其他方式无法支持的用例。在这种情况下,这两个标准都不适用。

在Java 8中,您可以在
AtomicInteger
中使用(和
updateAndGet

例如,如果我们想要有一个计数器,它在每次达到10时都归零

AtomicInteger counter = new AtomicInteger(0);

// to get & update
counter.getAndUpdate(value -> (value + 1) % 10)

他们只需要在框架中实现
get
compareAndSet
。所有其他方法都可以建立在这些基础上。聪明-但我怀疑在激烈的竞争下,这实际上会比同步执行得更差。@Michael,你能解释一下为什么吗?这与AtomicInteger自己的行为有什么不同吗?@Michael:问题是,
incrementAndGet()
的实现方式与他的方法一样,只是没有mod.Right,所以在这种情况下,你无论如何都不想使用原子类,这种情况基本上否定了这个问题的核心。很好的信息。这些方法不需要同步吗,科林?如果一个线程位于incrementAndGet()内部,并且增量已完成,但不是模,而另一个线程调用get(),并返回递增但不是模的值,该怎么办?@Mark:否。模是每个线程的本地值。
AtomicLong
将确保一旦对其调用了
incrementAndGet()
,调用
get()
的另一个线程将看到新值。然后,两个线程各自对值进行模化,每个线程都可以看到预期的最终结果。