面试题答案
一键面试可能遇到的性能问题
- 竞争激烈时的CAS自旋开销:AtomicInteger主要依靠CAS(Compare and Swap)操作来实现原子性。在高并发场景下,多个线程同时对AtomicInteger进行操作,可能会导致大量的CAS操作失败,线程需要不断自旋重试,这会消耗大量的CPU资源,降低系统性能。
优化方法及代码示例
- 减少不必要的原子操作:如果某些操作不需要原子性,可以将原子操作部分拆分出来,尽量减少在高并发场景下的原子操作频率。
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();
}
}
- 使用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在高竞争时,所有线程都竞争同一个变量,性能相对较差。