如果以线程安全方式溢出,则将AtomicInteger重置为零

fla*_*ash 2 java algorithm multithreading thread-safety

我有一个AtomicInteger由多个线程增加的.

如果它AtomicInteger以原子方式溢出,我想重置为零.我想确保counter变量值始终为正,因此只要clientCounter溢出或溢出,我会将AtomicInteger重置为零.我想出了下面的代码,但我不确定它是否是线程安全的,因为我正在添加检查和重置.有没有更好的方法来做到这一点?

  private static final AtomicInteger clientCounter = new AtomicInteger(0);

  // called by multiple threads
  public static int getCounter() {
    final int counter = clientCounter.incrementAndGet();

    // reset "clientCounter" to zero as soon as it overflow
    // basically I don't want "counter" value should be negative if it overflow
    // is below thread safe?
    if (counter + 1 < 0) {
      clientCounter.set(0);
    }

    if (counter % SIZE == 0) {
        // save counter in database
    }

    return counter;
  }
Run Code Online (Sandbox Code Playgroud)

更新:

下面是我的方法,我也使用newCounter值来保存在数据库中.我在数据库中保存的行,它要求newCounter作为最终变量,我不能newCounter在这里作为最终变量.现在该怎么解决?

  public static int getCounter() {
    int counter;
    int newCounter;
    do {
        counter = clientCounter.get();
        newCounter = counter < Integer.MAX_VALUE ? counter + 1 : 1;
    } while (!clientCounter.compareAndSet(counter, newCounter));

    if (newCounter % SIZE == 0) {
      Executors.newSingleThreadExecutor().execute(new Runnable() {
        @Override
        public void run() {
          // this is asking "newCounter" to make final
          DBClient.getInstance().save(newCounter);
        }
      });
    }

    return newCounter;
  }
Run Code Online (Sandbox Code Playgroud)

Dav*_*tat 6

如果我理解正确,我认为你需要compareAndSet这个.

int counter;
int newCounter;
do {
    counter = clientCounter.get();
    newCounter = counter < Integer.MAX_VALUE ? counter + 1 : 1;
} while (!clientCounter.compareAndSet(counter, newCounter));
return newCounter;
Run Code Online (Sandbox Code Playgroud)

  • @bhspencer不,compareAndSet的承诺保证在一个线程中循环继续. (2认同)