// 代码1
public class Sample {
  private static int count = 0;
  synchronized public static void increment() {
    count++;
  }
}

// 代码2
public class Sample {
  private static AtomicInteger count = new AtomicInteger(0);
  public static void increment() {
    count.getAndIncrement();
  }
}

虽然它们都可以实现相同的功能,那它们的区别到底是哪里呢?

synchronized

这个是最底层的锁的功能,是Java语言层次的关键字,用来进行同步操作。在使用了 synchronized 的代码块中,所有的线程在执行这段代码的时候,都会变成 串行 ,所以也就解决了多线程的问题。

Atomic

这种类型使用的是 CAS(Compare And Swap) 机制来进行修改的。这种类型的操作,不会使用锁来进行同步,它只是进行比较然后交换。想象下这种情况:

线程A:调用 get() ,假设它返回 1 线程A:计算它将要修改为新的值,这时期望它变成新值 2 (即原值为1,期望值为2) 同一时间 线程B:调用 get() ,假设它返回 1 线程B:计算它将要修改为新的值,这时期望它变成新值 2 (即原值为1,期望值为2)

CAS 只有在原值与原来的内存位置的值一样的时候,才会将原来内存位置的值设置为期望值(并且,这一个操作是原子性的,这个是由CPU保证它的原子的)

由于 atomic 的特特性,它只会允许一条线程设置成功,然后另一线设置失败,设置失败的线程,它会继续循环下一轮,直到成功为止。

假设这一轮是线程A设置成功了,线程B设置失败,所以线程B会继续 get() -> 比较 -> 设置为新的值 ,直到成功为止。所以,这种一般会有个死循环在这里一直尝试直至成功。

这种 CAS 是由CPU硬件提供的(如果所在平台的CPU并没有提供这种指令的话,那么Java会自行使用自旋来实现它,以达到平台独立的特性)

wikipedia