2025-04-30 21:56

`Integer` 和 `AtomicInteger` 的区别详解

王姐姐

Java后端

(73)

(0)

收藏

`Integer` 和 `AtomicInteger` 都是 Java 中用于表示整数的类,但它们在设计目的、线程安全性和使用场景上有显著区别。

一、基本特性对比

| 特性                | Integer                      | AtomicInteger               |

|---------------------|-----------------------------|-----------------------------|

| 包路径              | java.lang                   | java.util.concurrent.atomic |

| 可变性              | 不可变(immutable)           | 可变(mutable)               |

| 线程安全性          | 非线程安全                  | 线程安全                    |

| 原子操作支持        | 不支持                      | 支持                        |

| 适用场景            | 一般数值表示                | 并发环境下的计数器等        |

| 性能开销            | 低                          | 略高(因CAS操作)             |

二、核心区别详解

1. 可变性差异

Integer:

private final int value;  // 使用final修饰,不可变
public Integer(int value) {
    this.value = value;
}

- 一旦创建就不能修改其值

- 任何"修改"操作都会创建新对象

AtomicInteger:

private volatile int value;  // 可变,使用volatile保证可见性
public AtomicInteger(int initialValue) {
    value = initialValue;
}

- 可以直接修改内部值

- 提供`set()`、`get()`等方法直接操作值

2. 线程安全性

Integer:

- 基本操作非线程安全

- 多线程环境下需要额外同步

Integer count = 0;
// 线程不安全,需要同步
synchronized(lock) {
    count = count + 1;  // 自动装箱创建新对象
}

AtomicInteger:

- 内置线程安全保证

- 使用CAS(Compare-And-Swap)实现原子操作

AtomicInteger count = new AtomicInteger(0);
// 线程安全操作
count.incrementAndGet();  // 原子性自增

3. 原子操作支持

AtomicInteger 提供丰富的原子操作方法:

- `getAndIncrement()`: i++

- `incrementAndGet()`: ++i

- `getAndDecrement()`: i--

- `decrementAndGet()`: --i

- `getAndAdd(int delta)`: 获取当前值并加上delta

- `addAndGet(int delta)`: 加上delta并返回新值

- `compareAndSet(int expect, int update)`: CAS操作

Integer 完全不支持这些操作,所有算术运算都会创建新对象。

三、底层实现原理

Integer

- 基于基本类型int的包装类

- 值存储在final字段中

- 自动装箱/拆箱机制

AtomicInteger

- 使用Unsafe类实现底层操作

- 依赖CAS指令(CPU级别原子操作)

- volatile保证可见性

- 典型CAS实现:

public final int incrementAndGet() {
    return U.getAndAddInt(this, VALUE, 1) + 1;
}
// Unsafe中的实现
public final int getAndAddInt(Object o, long offset, int delta) {
    int v;
    do {
        v = getIntVolatile(o, offset);  // 获取当前值
    } while (!compareAndSwapInt(o, offset, v, v + delta));  // CAS尝试更新
    return v;
}

四、使用场景对比

适合使用Integer的场景

1. 作为方法参数或返回值传递整数值

2. 集合中的元素存储

3. 不需要修改的配置值

4. 非并发环境下的简单计数

适合使用AtomicInteger的场景

1. 高并发环境下的计数器

   // 统计请求次数
   private AtomicInteger requestCount = new AtomicInteger(0);
   
   void handleRequest() {
       requestCount.incrementAndGet();
       // ...
   }

2. 状态标志位

   private AtomicInteger status = new AtomicInteger(0);
   
   void changeStatus() {
       status.compareAndSet(0, 1);  // 只有当前是0时才改为1
   }

3. 序列号生成器

   private AtomicInteger seq = new AtomicInteger(0);
   
   int nextId() {
       return seq.getAndIncrement();
   }

五、性能考虑

1. 单线程环境:

   - Integer性能更好

   - AtomicInteger有额外的CAS开销

2. 低竞争多线程环境:

   - AtomicInteger表现良好

   - 比synchronized的Integer效率高

3. 高竞争环境:

   - AtomicInteger可能出现CAS失败重试

   - 可能需要考虑LongAdder(JDK8+)

六、典型错误用法

错误1:误以为Integer的原子性

Integer count = 0;
// 看似原子操作,实际是非原子的复合操作
count++;  
// 等效于:
// int temp = count.intValue();
// temp = temp + 1;
// count = Integer.valueOf(temp);

错误2:不必要的AtomicInteger使用

// 在单线程或不可变场景使用AtomicInteger是浪费
AtomicInteger id = new AtomicInteger(1);
System.out.println(id.get());  // 简单读取使用Integer即可

七、扩展比较

与synchronized的比较

// 使用synchronized实现线程安全计数
private int count = 0;
public synchronized void increment() {
    count++;
}
// 使用AtomicInteger实现
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
    count.incrementAndGet();
}

- AtomicInteger在低竞争下性能更好

- synchronized在高竞争下可能更稳定

与volatile的比较

private volatile int count = 0;
public void unsafeIncrement() {
    count++;  // 虽然是volatile,但++操作不是原子的
}

- volatile只保证可见性,不保证原子性

- AtomicInteger同时保证可见性和原子性

八、总结

1. 不可变 vs 可变:Integer设计为不可变类,AtomicInteger是可变且线程安全的

2. 简单 vs 复杂:Integer用于简单值传递,AtomicInteger用于并发控制

3. 性能取舍:单线程用Integer,并发计数用AtomicInteger,超高并发考虑LongAdder

4. 底层机制:AtomicInteger基于CAS和volatile实现无锁线程安全

根据具体场景选择合适的类型:

- 需要在线程间共享和修改的计数器 → AtomicInteger

- 作为方法参数或集合元素 → Integer

- 超高并发统计 → 考虑LongAdder(JDK8+)

0条评论

点击登录参与评论