Java中的AtomicInteger

时间:2020-02-23 14:36:08  来源:igfitidea点击:

今天,我们将研究Java中的" AtomicInteger"。
原子操作在单个任务单元中执行,而不受其他操作的干扰。
在多线程环境中,原子操作是必需的,以避免数据不一致。

原子整数

让我们创建一个简单的多线程程序,其中每个线程将共享的count变量递增4次。
因此,如果有两个线程,则在它们完成后," count"值应为8。

JavaAtomic.java

package com.theitroad.concurrency;

public class JavaAtomic {

  public static void main(String[] args) throws InterruptedException {

      ProcessingThread pt = new ProcessingThread();
      Thread t1 = new Thread(pt, "t1");
      t1.start();
      Thread t2 = new Thread(pt, "t2");
      t2.start();
      t1.join();
      t2.join();
      System.out.println("Processing count=" + pt.getCount());
  }

}

class ProcessingThread implements Runnable {
  private int count;

  @Override
  public void run() {
      for (int i = 1; i < 5; i++) {
          processSomething(i);
          count++;
      }
  }

  public int getCount() {
      return this.count;
  }

  private void processSomething(int i) {
      //processing some job
      try {
          Thread.sleep(i * 1000);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
  }

}

如果您在上述程序上运行,您会注意到count值在5,6,7,8之间变化。
原因是因为count ++不是原子操作。
因此,当一个线程读取其值并将其递增1时,另一线程读取了较早的值,从而导致错误的结果。

为了解决这个问题,我们必须确保对count的增量操作是原子的,我们可以使用Synchronization做到这一点,但是Java 5java.util.concurrent.atomic提供了int和long的包装类,可用于实现此原子操作,无需使用同步。

Java AtomicInteger示例

这是更新后的程序,该程序始终将计数值输出为8,因为" AtomicInteger"方法" incrementAndGet()"原子地将当前值加1。

package com.theitroad.concurrency;

import java.util.concurrent.atomic.AtomicInteger;

public class JavaAtomic {

  public static void main(String[] args) throws InterruptedException {

      ProcessingThread pt = new ProcessingThread();
      Thread t1 = new Thread(pt, "t1");
      t1.start();
      Thread t2 = new Thread(pt, "t2");
      t2.start();
      t1.join();
      t2.join();
      System.out.println("Processing count=" + pt.getCount());
  }
}

class ProcessingThread implements Runnable {
  private AtomicInteger count = new AtomicInteger();

  @Override
  public void run() {
      for (int i = 1; i < 5; i++) {
          processSomething(i);
          count.incrementAndGet();
      }
  }

  public int getCount() {
      return this.count.get();
  }

  private void processSomething(int i) {
      //processing some job
      try {
          Thread.sleep(i * 1000);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
  }

}

使用并发类进行原子操作的好处是我们不必担心同步。
这样可以提高代码的可读性,并减少出错的机会。
此外,假定原子操作并发类比涉及锁定资源的同步更为有效。