MST
星途 面试题库

面试题:Java中AtomicInteger在高并发场景下的性能优化

在高并发场景中使用AtomicInteger时,可能会遇到哪些性能问题?如何针对这些问题进行优化?请结合具体的代码示例阐述。
16.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

可能遇到的性能问题

  1. 竞争激烈时的CAS自旋开销:AtomicInteger主要依靠CAS(Compare and Swap)操作来实现原子性。在高并发场景下,多个线程同时对AtomicInteger进行操作,可能会导致大量的CAS操作失败,线程需要不断自旋重试,这会消耗大量的CPU资源,降低系统性能。

优化方法及代码示例

  1. 减少不必要的原子操作:如果某些操作不需要原子性,可以将原子操作部分拆分出来,尽量减少在高并发场景下的原子操作频率。
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerOptimization {
    private static AtomicInteger atomicInteger = new AtomicInteger(0);
    private static int normalValue = 0;

    public static void main(String[] args) {
        // 假设这里是高并发场景,多线程执行下面代码
        // 对于一些不需要原子性的操作,使用普通变量
        normalValue++;
        // 仅在需要原子性的关键操作时使用AtomicInteger
        atomicInteger.incrementAndGet();
    }
}
  1. 使用LongAdder(JDK 1.8引入)替代AtomicInteger:LongAdder在高并发场景下性能更好。它内部采用了分段锁的思想,当多个线程访问时,会分散到不同的Cell中进行操作,减少了竞争。
import java.util.concurrent.atomic.LongAdder;

public class LongAdderExample {
    private static LongAdder longAdder = new LongAdder();

    public static void main(String[] args) {
        // 模拟高并发场景
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    longAdder.increment();
                }
            });
            threads[i].start();
        }
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Final value: " + longAdder.sum());
    }
}

在上述代码中,LongAdder在高并发场景下通过分段存储,使得不同线程在不同Cell上操作,减少了竞争,从而提升了性能。而AtomicInteger在高竞争时,所有线程都竞争同一个变量,性能相对较差。