使用Java的Atomic类进行模块化增量

时间:2011-01-26 22:38:19

标签: java modulo atomicity

我很惊讶Java的AtomicInteger和AtomicLong类没有模块化增量的方法(因此在达到限制后值会回绕到零)。

我认为我必须遗漏一些明显的东西。最好的方法是什么?

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

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

5 个答案:

答案 0 :(得分:13)

从中读取时,只需修改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次提升是很多次增加(大约292年,每纳秒1次! )。

答案 1 :(得分:9)

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

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不提供这样的东西?谁知道,但我认为并发框架作者的意图是提供一些构建块,您可以使用它们来更好地创建自己的更高级别的功能。

答案 2 :(得分:4)

synchronized方法中添加addModular()修饰符或块有什么困难?

Atomic类不具备此功能的原因是它们基于当前CPU提供的specific atomic hardware instructions,并且无需借助锁定或其他操作的人无法实现模块化算法更复杂,效率最低的算法,如matt所建议的算法。

答案 3 :(得分:2)

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

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

AtomicInteger counter = new AtomicInteger(0);

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

答案 4 :(得分:1)

  

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

当标准课程不包括“花里胡哨”以支持各种不寻常的用例时,不要感到惊讶。设计师必须在它们包含的内容和它们不包含的内容上划一条线。趋势是支持常见用例和不可能以任何其他方式支持的用例。在这种情况下,这些标准都不适用。